X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gsupplicant%2Fsupplicant.c;h=e457fef247429d0bf870f835674cd39da4f369c5;hb=00b8c314dc2cfb641494d413f4b00d90a10ecbeb;hp=4f6957b92690a01f7cd0fd156938a6351a7cbb86;hpb=d04bfa0350781ebfb8cbb2e64fabdfb2f36cd302;p=platform%2Fupstream%2Fconnman.git diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c old mode 100644 new mode 100755 index 4f6957b..e457fef --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -40,19 +40,43 @@ #include "dbus.h" #include "gsupplicant.h" +#if defined TIZEN_EXT +#include "setting.h" +#endif + #define IEEE80211_CAP_ESS 0x0001 #define IEEE80211_CAP_IBSS 0x0002 #define IEEE80211_CAP_PRIVACY 0x0010 #if defined TIZEN_EXT +#define WLAN_EID_HT_CAP 45 +#define WLAN_EID_VHT_CAP 191 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_EXT_SUPP_RATES 50 #define COUNTRY_CODE_LENGTH 2 #endif +#if defined TIZEN_EXT +#define LAST_CONNECTED_TIMEOUT (5 * 60) +#define ASSOC_REJECT_TIMEOUT 10 +#define FREQ_RANGE_24GHZ_CHANNEL_1 2412 +#define FREQ_RANGE_24GHZ_CHANNEL_14 2484 +#define FREQ_RANGE_5GHZ_CHANNEL_32 5160 +#define FREQ_RANGE_5GHZ_CHANNEL_165 5825 + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + #define BSS_UNKNOWN_STRENGTH -90 static DBusConnection *connection; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +static GSupplicantCallbacks *callbacks_pointer; +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ static const GSupplicantCallbacks *callbacks_pointer; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ static dbus_bool_t system_available = FALSE; static dbus_bool_t system_ready = FALSE; @@ -96,8 +120,10 @@ static struct strvalmap keymgmt_map[] = { { "wpa-eap", G_SUPPLICANT_KEYMGMT_WPA_EAP }, { "wpa-eap-sha256", G_SUPPLICANT_KEYMGMT_WPA_EAP_256 }, { "wps", G_SUPPLICANT_KEYMGMT_WPS }, -#if defined TIZEN_EXT_WIFI_MESH +#if defined TIZEN_EXT { "sae", G_SUPPLICANT_KEYMGMT_SAE }, + { "owe", G_SUPPLICANT_KEYMGMT_OWE }, + { "dpp", G_SUPPLICANT_KEYMGMT_DPP }, #endif { } }; @@ -148,6 +174,28 @@ static struct strvalmap mode_capa_map[] = { { } }; +#if defined TIZEN_EXT && defined TIZEN_EXT_INS +struct _GSupplicantINSSettings { + GSupplicantINSPreferredFreq preferred_freq_bssid; + unsigned int preferred_freq_bssid_score; + bool last_connected_bssid; + unsigned int last_connected_bssid_score; + bool assoc_reject; + unsigned int assoc_reject_score; + bool signal_bssid; + int signal_level3_5ghz; + int signal_level3_24ghz; +}; + +static struct _GSupplicantINSSettings ins_settings; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ + +#if defined TIZEN_EXT +static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + static GHashTable *interface_table; static GHashTable *bss_mapping; static GHashTable *peer_mapping; @@ -166,6 +214,11 @@ struct added_network_information { GSupplicantSecurity security; char * passphrase; char * private_passphrase; +#if defined TIZEN_EXT + char *connector; + char *c_sign_key; + char *net_access_key; +#endif }; #if defined TIZEN_EXT_WIFI_MESH @@ -210,8 +263,13 @@ struct _GSupplicantInterface { GSupplicantNetwork *current_network; struct added_network_information network_info; #if defined TIZEN_EXT + dbus_bool_t is_5_0_Ghz_supported; int disconnect_reason; #endif +#if defined TIZEN_EXT + unsigned char add_network_bssid[WIFI_BSSID_LEN_MAX]; + unsigned char connected_bssid[WIFI_BSSID_LEN_MAX]; +#endif #if defined TIZEN_EXT_WIFI_MESH bool mesh_support; struct _GSupplicantMeshGroupInfo group_info; @@ -246,10 +304,20 @@ struct g_supplicant_bss { GSList *vsie_list; dbus_bool_t hs20; unsigned char country_code[COUNTRY_CODE_LENGTH]; + GSupplicantPhy_mode phy_mode; + dbus_int16_t snr; + dbus_uint32_t est_throughput; #endif unsigned int wps_capabilities; -#if defined TIZEN_EXT_WIFI_MESH +#if defined TIZEN_EXT dbus_bool_t sae; + dbus_bool_t owe; + dbus_bool_t dpp; + dbus_bool_t owe_transition_mode; + unsigned int transition_mode_ssid_len; + unsigned char transition_mode_bssid[6]; + unsigned char transition_mode_ssid[32]; + dbus_bool_t pmf_required; #endif }; @@ -277,6 +345,14 @@ struct _GSupplicantNetwork { unsigned int keymgmt; GSList *vsie_list; unsigned char country_code[COUNTRY_CODE_LENGTH]; + GSupplicantPhy_mode phy_mode; + dbus_bool_t owe_transition_mode; + dbus_bool_t privacy; + unsigned int transition_mode_ssid_len; + unsigned char transition_mode_bssid[6]; + unsigned char transition_mode_ssid[32]; + unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX]; + GHashTable *assoc_reject_table; #endif }; @@ -314,10 +390,24 @@ struct interface_data { GSupplicantSSID *ssid; }; +#if defined TIZEN_EXT +struct interface_signalpoll_data { + GSupplicantInterface *interface; + char *path; + GSupplicantMaxSpeedCallback callback; + void *user_data; +}; +#endif + struct interface_create_data { char *ifname; char *driver; char *bridge; +#if defined TIZEN_EXT + unsigned int mac_addr; + unsigned int preassoc_mac_addr; + unsigned int random_mac_lifetime; +#endif /* TIZEN_EXT */ #if defined TIZEN_EXT_WIFI_MESH char *parent_ifname; bool is_mesh_interface; @@ -347,11 +437,25 @@ struct interface_scan_data { }; #if defined TIZEN_EXT -struct g_connman_bssids { - char bssid[18]; - uint16_t strength; - uint16_t frequency; +struct update_bssid_data { + GSupplicantNetwork *network; + unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX]; + GHashTable *assoc_reject_table; + GSList *bssid_list; +}; + +struct assoc_reject_data { + char *bssid; + GSList *reject_time_list; +}; + +struct assoc_count_data { + time_t ref_time; + int assoc_count; }; + +static unsigned int last_connected_bss_timeout = 0; +static bool simplified_log = true; #endif static int network_remove(struct interface_data *data); @@ -438,10 +542,12 @@ static const char *security2string(GSupplicantSecurity security) return "ft_psk"; case G_SUPPLICANT_SECURITY_FT_IEEE8021X: return "ft_ieee8021x"; -#endif -#if defined TIZEN_EXT_WIFI_MESH case G_SUPPLICANT_SECURITY_SAE: return "sae"; + case G_SUPPLICANT_SECURITY_OWE: + return "owe"; + case G_SUPPLICANT_SECURITY_DPP: + return "dpp"; #endif } @@ -505,6 +611,23 @@ static bool compare_network_parameters(GSupplicantInterface *interface, return FALSE; } +#if defined TIZEN_EXT + if (interface->network_info.connector && + g_strcmp0(interface->network_info.connector, + ssid->connector) != 0) { + return FALSE; + } + if (interface->network_info.c_sign_key && + g_strcmp0(interface->network_info.c_sign_key, + ssid->c_sign_key) != 0) { + return FALSE; + } + if (interface->network_info.net_access_key && + g_strcmp0(interface->network_info.net_access_key, + ssid->net_access_key) != 0) { + return FALSE; + } +#endif return TRUE; } @@ -513,9 +636,19 @@ static void remove_network_information(GSupplicantInterface * interface) g_free(interface->network_info.ssid); g_free(interface->network_info.passphrase); g_free(interface->network_info.private_passphrase); +#if defined TIZEN_EXT + g_free(interface->network_info.connector); + g_free(interface->network_info.c_sign_key); + g_free(interface->network_info.net_access_key); +#endif interface->network_info.ssid = NULL; interface->network_info.passphrase = NULL; interface->network_info.private_passphrase = NULL; +#if defined TIZEN_EXT + interface->network_info.connector = NULL; + interface->network_info.c_sign_key = NULL; + interface->network_info.net_access_key = NULL; +#endif } static int store_network_information(GSupplicantInterface * interface, @@ -534,6 +667,9 @@ static int store_network_information(GSupplicantInterface * interface, if ((ssid->security == G_SUPPLICANT_SECURITY_WEP || ssid->security == G_SUPPLICANT_SECURITY_PSK || +#if defined TIZEN_EXT + ssid->security == G_SUPPLICANT_SECURITY_SAE || +#endif ssid->security == G_SUPPLICANT_SECURITY_NONE) && ssid->passphrase) { interface->network_info.passphrase = g_strdup(ssid->passphrase); @@ -723,6 +859,17 @@ static void callback_assoc_failed(void *user_data) callbacks_pointer->assoc_failed(user_data); } + +static void callback_scan_done(GSupplicantInterface *interface) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->scan_done) + return; + + callbacks_pointer->scan_done(interface); +} #endif static void callback_network_changed(GSupplicantNetwork *network, @@ -748,6 +895,43 @@ static void callback_network_associated(GSupplicantNetwork *network) callbacks_pointer->network_associated(network); } +static void callback_sta_authorized(GSupplicantInterface *interface, + const char *addr) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->sta_authorized) + return; + + callbacks_pointer->sta_authorized(interface, addr); +} + +static void callback_sta_deauthorized(GSupplicantInterface *interface, + const char *addr) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->sta_deauthorized) + return; + + callbacks_pointer->sta_deauthorized(interface, addr); +} + +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +static void callback_eap(GSupplicantInterface *interface, bool status) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->eap) + return; + + callbacks_pointer->eap(interface, status); +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + static void callback_peer_found(GSupplicantPeer *peer) { if (!callbacks_pointer) @@ -881,6 +1065,9 @@ static void remove_network(gpointer data) callback_network_removed(network); g_hash_table_destroy(network->config_table); +#if defined TIZEN_EXT + g_hash_table_destroy(network->assoc_reject_table); +#endif g_free(network->path); g_free(network->group); @@ -901,6 +1088,8 @@ static void remove_bss(gpointer data) { struct g_supplicant_bss *bss = data; + supplicant_dbus_property_call_cancel_all(bss); + g_free(bss->path); #if defined TIZEN_EXT g_slist_free_full(bss->vsie_list, g_free); @@ -931,11 +1120,25 @@ static void remove_peer(gpointer data) g_free(peer); } +#if defined TIZEN_EXT +static void remove_assoc_data(gpointer data) +{ + struct assoc_reject_data *assoc_data = data; + + g_free(assoc_data->bssid); + g_slist_free(assoc_data->reject_time_list); + + g_free(assoc_data); +} +#endif + static void debug_strvalmap(const char *label, struct strvalmap *map, unsigned int val) { int i; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif for (i = 0; map[i].str; i++) { if (val & map[i].val) SUPPLICANT_DBG("%s: %s", label, map[i].str); @@ -1098,12 +1301,36 @@ static void interface_capability(const char *key, DBusMessageIter *iter, if (max_scan_ssid < 2) max_scan_ssid = 0; interface->max_scan_ssids = max_scan_ssid; +#if defined TIZEN_EXT + } else if (g_strcmp0(key, "Is5GhzSupported") == 0) { + dbus_bool_t is_5_0_Ghz_supported; + dbus_message_iter_get_basic(iter, &is_5_0_Ghz_supported); + interface->is_5_0_Ghz_supported = is_5_0_Ghz_supported; +#endif } else SUPPLICANT_DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter)); } +static void set_bss_expiration_age(DBusMessageIter *iter, void *user_data) +{ + unsigned int bss_expiration_age = GPOINTER_TO_UINT(user_data); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, + &bss_expiration_age); +} + +int g_supplicant_interface_set_bss_expiration_age(GSupplicantInterface *interface, + unsigned int bss_expiration_age) +{ + return supplicant_dbus_property_set(interface->path, + SUPPLICANT_INTERFACE ".Interface", + "BSSExpireAge", DBUS_TYPE_UINT32_AS_STRING, + set_bss_expiration_age, NULL, + GUINT_TO_POINTER(bss_expiration_age), NULL); +} + struct set_apscan_data { unsigned int ap_scan; @@ -1187,6 +1414,24 @@ const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface) return interface->ifname; } +#if defined TIZEN_EXT +bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface) +{ + if (!interface) + return NULL; + + return interface->is_5_0_Ghz_supported; +} + +unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface) +{ + if (!interface) + return NULL; + + return (unsigned char *)interface->add_network_bssid; +} +#endif + const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface) { if (!interface) @@ -1356,6 +1601,32 @@ dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network) return network->signal; } +#if defined TIZEN_EXT +void g_supplicant_network_set_signal(GSupplicantNetwork *network, int signal) +{ + if (!network) + return; + + network->signal = (dbus_int16_t)signal; +} + +void g_supplicant_network_set_bss_signal(GSupplicantNetwork *network, + int signal, int snr) +{ + struct g_supplicant_bss *best_bss; + + if (!network) + return; + + best_bss = network->best_bss; + if (!best_bss) + return; + + best_bss->signal = (dbus_int16_t)signal; + best_bss->snr = (dbus_int16_t)snr; +} +#endif + dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network) { if (!network) @@ -1405,6 +1676,16 @@ dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network) return FALSE; } +#ifdef TIZEN_EXT +GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network) +{ + if (!network) + return G_SUPPLICANT_MODE_IEEE80211_UNKNOWN; + + return network->phy_mode; +} +#endif + GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer) { if (!peer) @@ -1488,12 +1769,20 @@ const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network) unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network) { - if (network == NULL) + if (!network) return 0; return network->keymgmt; } +dbus_bool_t g_supplicant_network_get_privacy(GSupplicantNetwork *network) +{ + if (!network) + return FALSE; + + return network->privacy; +} + const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork *network) { @@ -1502,6 +1791,14 @@ const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork return network->country_code; } + +dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network) +{ + if (!network) + return 0; + + return network->best_bss->pmf_required; +} #endif const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer, @@ -1598,6 +1895,34 @@ const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network) return (const unsigned char *)network->best_bss->bssid; } +dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network) +{ + if (network == NULL) + return FALSE; + + return network->owe_transition_mode; +} + +const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network) +{ + if (network == NULL) + return NULL; + + return (const unsigned char *)network->transition_mode_bssid; +} + +const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network, + unsigned int *transition_mode_ssid_len) +{ + if (!network) { + *transition_mode_ssid_len = 0; + return NULL; + } + + *transition_mode_ssid_len = network->transition_mode_ssid_len; + return network->transition_mode_ssid; +} + unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network) { if (network == NULL || network->best_bss == NULL) @@ -1612,7 +1937,10 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network) return NULL; if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK || - network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) { + network->best_bss->security == G_SUPPLICANT_SECURITY_SAE || + network->best_bss->security == G_SUPPLICANT_SECURITY_OWE || + network->best_bss->security == G_SUPPLICANT_SECURITY_DPP || + network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) { unsigned int pairwise; pairwise = network->best_bss->rsn_pairwise | @@ -1639,6 +1967,10 @@ bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network) if (network == NULL || network->best_bss == NULL) return 0; + if (network->best_bss->security == G_SUPPLICANT_SECURITY_OWE || + network->best_bss->security == G_SUPPLICANT_SECURITY_DPP) + return false; + if (network->best_bss->rsn_selected) { const char *mode = g_supplicant_network_get_enc_mode(network); if (g_strcmp0(mode, "aes") == 0 || @@ -1677,101 +2009,431 @@ void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network) return vsie_list; } -static void update_bssid_list(gpointer key, gpointer value, gpointer user_data) +static bool compare_bssid(unsigned char *bssid_a, unsigned char *bssid_b) { - struct g_supplicant_bss *bss = value; - struct g_connman_bssids *bssids = NULL; - char buff[18]; - GSList **list = (GSList **)user_data; + if (!memcmp(bssid_a, bssid_b, WIFI_BSSID_LEN_MAX)) + return true; - bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids)); + return false; +} - if (bssids) { - g_snprintf(buff, 18, "%02x:%02x:%02x:%02x:%02x:%02x", - bss->bssid[0], bss->bssid[1], bss->bssid[2], bss->bssid[3], - bss->bssid[4], bss->bssid[5]); +static gchar *convert_bssid_to_str(unsigned char *bssid) +{ + GString *bssid_str; + unsigned int i; - memcpy(bssids->bssid, buff, 18); - bssids->bssid[17] = '\0'; - bssids->strength = bss->signal; - bssids->strength += 120; + bssid_str = g_string_sized_new(18); + if (!bssid_str) + return NULL; - if (bssids->strength > 100) - bssids->strength = 100; + for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) { + g_string_append_printf(bssid_str, "%02x", bssid[i]); + if (i < WIFI_BSSID_LEN_MAX - 1) + g_string_append(bssid_str, ":"); + } - bssids->frequency = bss->frequency; - *list = g_slist_append(*list, bssids); - } else - SUPPLICANT_DBG("Failed to allocate memory"); + return g_string_free(bssid_str, FALSE); } -void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network) +#if defined TIZEN_EXT_INS +static void count_assoc_reject(gpointer data, gpointer user_data) { - GSList *bssid_list = NULL; - - if (g_hash_table_size(network->bss_table) < 1) - return NULL; + time_t assoc_reject_time = GPOINTER_TO_INT(data); + struct assoc_count_data *assoc_count = user_data; - g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_list); - - return bssid_list; + if (assoc_reject_time > assoc_count->ref_time) + assoc_count->assoc_count++; } -#endif -static void merge_network(GSupplicantNetwork *network) +static uint16_t get_assoc_reject_cnt(GHashTable *assoc_reject_table, unsigned char *bssid) { - GString *str; - const char *ssid, *mode, *key_mgmt; -#if defined TIZEN_EXT - const char *isHS20AP; - const char *eap, *identity, *phase2; -#endif - unsigned int i, ssid_len; - char *group; + gchar *bssid_str; + struct assoc_reject_data *assoc_data; + struct assoc_count_data assoc_count; + time_t curr_time; + struct tm* timeinfo; - ssid = g_hash_table_lookup(network->config_table, "ssid"); - mode = g_hash_table_lookup(network->config_table, "mode"); - key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt"); -#if defined TIZEN_EXT - isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP"); - eap = g_hash_table_lookup(network->config_table, "eap"); - identity = g_hash_table_lookup(network->config_table, "identity"); - phase2 = g_hash_table_lookup(network->config_table, "phase2"); -#endif + if (g_hash_table_size(assoc_reject_table) < 1) + return 0; - SUPPLICANT_DBG("ssid %s mode %s", ssid, mode); + if (!bssid) + return 0; - if (ssid) - ssid_len = strlen(ssid); - else - ssid_len = 0; + if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) + return 0; - str = g_string_sized_new((ssid_len * 2) + 24); - if (!str) - return; + bssid_str = convert_bssid_to_str(bssid); + if (!bssid_str) + return 0; - for (i = 0; i < ssid_len; i++) -#if defined TIZEN_EXT - { - if (ssid[i] != '"') -#endif - g_string_append_printf(str, "%02x", ssid[i]); -#if defined TIZEN_EXT + assoc_data = g_hash_table_lookup(assoc_reject_table, bssid_str); + if (!assoc_data) { + g_free(bssid_str); + return 0; } -#endif - if (g_strcmp0(mode, "0") == 0) - g_string_append_printf(str, "_managed"); - else if (g_strcmp0(mode, "1") == 0) - g_string_append_printf(str, "_adhoc"); -#if defined TIZEN_EXT_WIFI_MESH - else if (g_strcmp0(mode, "5") == 0) - g_string_append_printf(str, "_mesh"); -#endif + if (g_slist_length(assoc_data->reject_time_list) < 1) { + g_free(bssid_str); + return 0; + } - if (g_strcmp0(key_mgmt, "WPA-PSK") == 0) - g_string_append_printf(str, "_psk"); -#if defined TIZEN_EXT + /* Only events that occur within one hour are appened. */ + curr_time = time(NULL); + timeinfo = localtime(&curr_time); + timeinfo->tm_hour -= 1; + + assoc_count.ref_time = mktime(timeinfo); + assoc_count.assoc_count = 0; + + g_slist_foreach(assoc_data->reject_time_list, count_assoc_reject, &assoc_count); + + g_free(bssid_str); + return assoc_count.assoc_count; +} + +static int calculate_score_last_connected_bssid(bool is_last_connected) +{ + int score = 0; + + if (ins_settings.last_connected_bssid) { + if (is_last_connected) + score += ins_settings.last_connected_bssid_score; + } + + return score; +} + +static int calculate_score_assoc_reject(uint16_t assoc_reject_cnt) +{ + int score = 0; + + if (ins_settings.assoc_reject) + score -= (assoc_reject_cnt * ins_settings.assoc_reject_score); + + return score; +} + +static int calculate_score_frequency(dbus_int16_t strength, dbus_uint16_t frequency) +{ + int score = 0; + + switch (ins_settings.preferred_freq_bssid) { + case G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ: + if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 && + frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) && + (strength > ins_settings.signal_level3_24ghz)) + score += ins_settings.preferred_freq_bssid_score; + + break; + case G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ: + if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 && + frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) && + (strength > ins_settings.signal_level3_5ghz)) + score += ins_settings.preferred_freq_bssid_score; + + break; + default: + break; + } + + return score; +} + +static int calculate_score_strength(dbus_int16_t strength) +{ + int score = 0; + + if (ins_settings.signal_bssid) + score += (((strength > -60) ? -60 : strength) + 85); + + return score; +} + +static int calculate_score_est_throughput(dbus_uint32_t est_throughput) +{ + int score = 0; + + if (est_throughput >= 10000) + score = est_throughput / 10000; + + if (score > 40) + score = 40; + + return score; +} + +static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt, + dbus_uint16_t frequency, dbus_int16_t strength, + dbus_int16_t snr, dbus_uint32_t est_throughput) +{ + int score = 0; + + score += calculate_score_last_connected_bssid(is_last_connected); + score += calculate_score_assoc_reject(assoc_reject_cnt); + score += calculate_score_frequency(strength, frequency); + score += calculate_score_strength(strength); + score += (int)snr; + score += calculate_score_est_throughput(est_throughput); + + return score; +} +#endif + +static void update_bssid_list(gpointer key, gpointer value, gpointer user_data) +{ + struct g_supplicant_bss *bss = value; + struct g_connman_bssids *bssids = NULL; + struct update_bssid_data *bssid_data = (struct update_bssid_data *)user_data; + + bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids)); + + if (bssids) { + memcpy(bssids->bssid, bss->bssid, WIFI_BSSID_LEN_MAX); + + bssids->strength = bss->signal; + bssids->strength += 120; + + if (bssids->strength > 100) + bssids->strength = 100; + + bssids->frequency = bss->frequency; + bssids->score_snr = (int)bss->snr; + +#if defined TIZEN_EXT_INS + bssids->assoc_reject_cnt = get_assoc_reject_cnt(bssid_data->assoc_reject_table, bssids->bssid); + bssids->is_last_connected = compare_bssid(bssids->bssid, bssid_data->last_connected_bssid); + + bssids->score_last_connected_bssid = calculate_score_last_connected_bssid(bssids->is_last_connected); + bssids->score_assoc_reject = calculate_score_assoc_reject(bssids->assoc_reject_cnt); + bssids->score_frequency = calculate_score_frequency(bss->signal, bssids->frequency); + bssids->score_strength = calculate_score_strength(bss->signal); + bssids->score_est_throughput = calculate_score_est_throughput(bss->est_throughput); + + bssids->ins_score = calculate_score(bssids->is_last_connected, + bssids->assoc_reject_cnt, bssids->frequency, bss->signal, + bss->snr, bss->est_throughput); +#else + bssids->ins_score = bss->signal; +#endif + bssid_data->bssid_list = g_slist_append(bssid_data->bssid_list, bssids); + } else + SUPPLICANT_DBG("Failed to allocate memory"); +} + +static gint cmp_bss(gconstpointer a, gconstpointer b) +{ + struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a; + struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b; + + if (entry_a->ins_score > entry_b->ins_score) + return -1; + + if (entry_a->ins_score < entry_b->ins_score) + return 1; + + return 0; +} + +#if defined TIZEN_EXT_INS +static void print_bssid_sort(gpointer data, gpointer user_data) +{ + struct g_connman_bssids *bssids = data; + + SUPPLICANT_DBG("bssid[" MACSTR "] total[%2d] freq[%2d] " + "last_conn[%2d] assoc_reject[%2d] strength[%2d]", + MAC2STR(bssids->bssid), bssids->ins_score, + bssids->score_frequency, bssids->score_last_connected_bssid, + bssids->score_assoc_reject, bssids->score_strength); +} +#endif + +void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network) +{ + struct update_bssid_data bssid_data; + + if (g_hash_table_size(network->bss_table) < 1) + return NULL; + + bssid_data.network = network; + memset(&bssid_data, 0, sizeof(bssid_data)); + memcpy(bssid_data.last_connected_bssid, network->last_connected_bssid, WIFI_BSSID_LEN_MAX); + bssid_data.assoc_reject_table = network->assoc_reject_table; + + g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_data); + bssid_data.bssid_list = g_slist_sort(bssid_data.bssid_list, cmp_bss); +#if defined TIZEN_EXT_INS + g_slist_foreach(bssid_data.bssid_list, print_bssid_sort, NULL); +#endif + + return bssid_data.bssid_list; +} + +void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid) +{ + if (!bssid) + return; + + if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) + return; + + memcpy(network->last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX); + + SUPPLICANT_DBG("last connected bssid [" MACSTR "]", MAC2STR(bssid)); +} + +const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network) +{ + if (network == NULL) + return NULL; + + return (const unsigned char *)network->last_connected_bssid; +} + +void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface, + GSupplicantNetwork *network) +{ + struct assoc_reject_data *assoc_data; + gchar *bssid_str; + time_t curr_time; + + if (!network) + return; + + bssid_str = convert_bssid_to_str(interface->add_network_bssid); + if (!bssid_str) + return; + + assoc_data = g_hash_table_lookup(network->assoc_reject_table, bssid_str); + if (!assoc_data) { + assoc_data = g_try_new0(struct assoc_reject_data, 1); + if (!assoc_data) { + g_free(bssid_str); + return; + } + + assoc_data->bssid = g_strdup(bssid_str); + g_hash_table_insert(network->assoc_reject_table, assoc_data->bssid, assoc_data); + } + + curr_time = time(NULL); + assoc_data->reject_time_list = g_slist_append(assoc_data->reject_time_list, GINT_TO_POINTER(curr_time)); + + SUPPLICANT_DBG("bssid [%s] time [%u]", bssid_str, curr_time); + + g_free(bssid_str); + + callback_network_changed(network, "UpdateAssocReject"); +} + +GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network) +{ + if (!network) + return NULL; + + return network->assoc_reject_table; +} + +GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface, + const char *group) +{ + if (!interface) + return NULL; + + return g_hash_table_lookup(interface->network_table, group); +} + +static void copy_assoc_reject(gpointer key, gpointer value, gpointer user_data) +{ + struct assoc_reject_data *cloned_assoc_data; + struct assoc_reject_data *assoc_data = value; + GHashTable *cloned_assoc_reject_table = user_data; + + if (assoc_data && cloned_assoc_reject_table) { + cloned_assoc_data = g_try_new0(struct assoc_reject_data, 1); + if (!cloned_assoc_data) + return; + + cloned_assoc_data->bssid = g_strdup(assoc_data->bssid); + cloned_assoc_data->reject_time_list = g_slist_copy(assoc_data->reject_time_list); + g_hash_table_insert(cloned_assoc_reject_table, + cloned_assoc_data->bssid, cloned_assoc_data); + } +} + +GHashTable *g_supplicant_network_clone_assoc_reject_table(GSupplicantNetwork *network) +{ + GHashTable *cloned_assoc_reject_table; + + if (!network) + return NULL; + + GHashTable *assoc_reject_table = g_supplicant_network_get_assoc_reject_table(network); + if (!assoc_reject_table) + return NULL; + + cloned_assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, remove_assoc_data); + g_hash_table_foreach(assoc_reject_table, copy_assoc_reject, cloned_assoc_reject_table); + + return cloned_assoc_reject_table; +} + +#endif + +static void merge_network(GSupplicantNetwork *network) +{ + GString *str; + const char *ssid, *mode, *key_mgmt; +#if defined TIZEN_EXT + const char *isHS20AP; + const char *eap, *identity, *phase2; +#endif + unsigned int i, ssid_len; + char *group; + + ssid = g_hash_table_lookup(network->config_table, "ssid"); + mode = g_hash_table_lookup(network->config_table, "mode"); + key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt"); +#if defined TIZEN_EXT + isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP"); + eap = g_hash_table_lookup(network->config_table, "eap"); + identity = g_hash_table_lookup(network->config_table, "identity"); + phase2 = g_hash_table_lookup(network->config_table, "phase2"); +#endif + + SUPPLICANT_DBG("ssid %s mode %s", ssid, mode); + + if (ssid) + ssid_len = strlen(ssid); + else + ssid_len = 0; + + str = g_string_sized_new((ssid_len * 2) + 24); + if (!str) + return; + + for (i = 0; i < ssid_len; i++) +#if defined TIZEN_EXT + { + if (ssid[i] != '"') +#endif + g_string_append_printf(str, "%02x", ssid[i]); +#if defined TIZEN_EXT + } +#endif + + if (g_strcmp0(mode, "0") == 0) + g_string_append_printf(str, "_managed"); + else if (g_strcmp0(mode, "1") == 0) + g_string_append_printf(str, "_adhoc"); +#if defined TIZEN_EXT_WIFI_MESH + else if (g_strcmp0(mode, "5") == 0) + g_string_append_printf(str, "_mesh"); +#endif + + if (g_strcmp0(key_mgmt, "WPA-PSK") == 0) + g_string_append_printf(str, "_psk"); +#if defined TIZEN_EXT else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0) g_string_append_printf(str, "_ieee8021x"); else @@ -1883,7 +2545,6 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data) static void interface_network_removed(DBusMessageIter *iter, void *user_data) { SUPPLICANT_DBG(""); - return; } static char *create_name(unsigned char *ssid, int ssid_len) @@ -1953,12 +2614,69 @@ static char *create_group(struct g_supplicant_bss *bss) return g_string_free(str, FALSE); } +#if defined TIZEN_EXT +static void update_network_with_best_bss(GSupplicantNetwork *network, + struct g_supplicant_bss *best_bss) +{ + /* + * Do not change best BSS if we are connected. + */ + if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED) + return; + + network->signal = best_bss->signal; + network->frequency = best_bss->frequency; + network->best_bss = best_bss; +} + +static bool update_best_bss(GSupplicantNetwork *network, + struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss) +{ + int score_new; + int score_best; + if (network->best_bss == NULL) { + update_network_with_best_bss(network, bss); + return true; + } + +#if defined TIZEN_EXT_INS + score_new = calculate_score( + compare_bssid(bss->bssid, network->last_connected_bssid), + get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid), + bss->frequency, bss->signal, bss->snr, bss->est_throughput); + + score_best = calculate_score( + compare_bssid(network->best_bss->bssid, network->last_connected_bssid), + get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid), + network->best_bss->frequency, network->best_bss->signal, + network->best_bss->snr, network->best_bss->est_throughput); +#else + score_new = bss->signal; + score_best = network->best_bss->signal; +#endif + + if (score_new > score_best) { + SUPPLICANT_DBG("new[" MACSTR "][%d] : best[" MACSTR "][%d]", + MAC2STR(bss->bssid), score_new, + MAC2STR(network->best_bss->bssid), score_best); + + update_network_with_best_bss(network, bss); + + SUPPLICANT_DBG("Update best BSS for %s", network->name); + + return true; + } + + return false; +} +#endif static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) { GSupplicantInterface *interface = bss->interface; GSupplicantNetwork *network; char *group; + bool is_new_network; group = create_group(bss); SUPPLICANT_DBG("New group created: %s", group); @@ -1970,10 +2688,13 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) if (network) { g_free(group); SUPPLICANT_DBG("Network %s already exist", network->name); + is_new_network = false; goto done; } + is_new_network = true; + network = g_try_new0(GSupplicantNetwork, 1); if (!network) { g_free(group); @@ -1993,7 +2714,17 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network->frequency = bss->frequency; network->best_bss = bss; + if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) { + network->wps = TRUE; + network->wps_capabilities = bss->wps_capabilities; + } + #if defined TIZEN_EXT + network->owe_transition_mode = bss->owe_transition_mode; + network->privacy = bss->privacy; + memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len); + memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX); + network->keymgmt = bss->keymgmt; if (g_slist_length(bss->vsie_list) > 0) { @@ -2013,6 +2744,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network->isHS20AP = bss->hs20; memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH); + network->phy_mode = bss->phy_mode; #endif SUPPLICANT_DBG("New network %s created", network->name); @@ -2023,6 +2755,11 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); +#if defined TIZEN_EXT + network->assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, remove_assoc_data); +#endif + g_hash_table_replace(interface->network_table, network->group, network); @@ -2032,19 +2769,29 @@ done: /* We update network's WPS properties if only bss provides WPS. */ if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) { network->wps = TRUE; - network->wps_capabilities |= bss->wps_capabilities; + network->wps_capabilities = bss->wps_capabilities; + + if (!is_new_network) + callback_network_changed(network, "WPSCapabilities"); } /* * Do not change best BSS if we are connected. It will be done through * CurrentBSS property in case of misalignment with wpa_s or roaming. */ +#if defined TIZEN_EXT + if (network != interface->current_network) { + if (update_best_bss(network, bss, network->best_bss)) + callback_network_changed(network, "Signal"); + } +#else if (network != interface->current_network && bss->signal > network->signal) { network->signal = bss->signal; network->best_bss = bss; callback_network_changed(network, "Signal"); } +#endif g_hash_table_replace(interface->bss_mapping, bss->path, network); g_hash_table_replace(network->bss_table, bss->path, bss); @@ -2195,6 +2942,50 @@ static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size, return 0; } +#if defined TIZEN_EXT +static void get_bss_phy_mode(unsigned int max_rate, + unsigned int max_ext_rate, bool ht, bool vht, void *data) +{ + struct g_supplicant_bss *bss = data; + unsigned int freq = bss->frequency; + + /* Following conditions are used to determine + * IEEE 802.11 Protocol Modes:- + * + * 1. If “Supported rates” is only till 11 Mbps, + * and frequency is in 2.4GHz band, then protocol is 11B. + * 2. If “Supported rates” is till 54Mbps or + * “Extended supported rates” are present, + * and frequency is in 2.4GHz band, then protocol is 11G. + * 3. If “Supported rates” is only till 54 Mbps, + * frequency is in 5GHz band , then protocol is 11A. + * 4. If “HT capabilities” is supported , then protocol is 11N. + * 5. If “HT capabilities” & “VHT” is supported and + * frequency is in 5 GHz band, then protocol is 11AC. + * */ + + if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */ + if (max_rate <= 11 && max_ext_rate <= 0 && !ht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B; + else if ((max_rate <= 54 || max_ext_rate > 0) && !ht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG; + else if ((max_rate >= 54 || max_ext_rate > 0) && ht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN; + else + bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN; + } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */ + if (max_rate <= 54 && !ht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A; + else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN; + else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht) + bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC; + else + bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN; + } +} +#endif + static void bss_process_ies(DBusMessageIter *iter, void *user_data) { struct g_supplicant_bss *bss = user_data; @@ -2203,6 +2994,17 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) DBusMessageIter array; unsigned int value; int ie_len; +#if defined TIZEN_EXT + const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c }; + int r_len, j; + unsigned char *rates = NULL; + unsigned char *ext_rates = NULL; + unsigned int max_rate = 0; + unsigned int max_ext_rate = 0; + unsigned int offset = 0; + bool ht = false; + bool vht = false; +#endif #define WMM_WPA1_WPS_INFO 221 #define WPS_INFO_MIN_LEN 6 @@ -2217,6 +3019,8 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) #if defined TIZEN_EXT #define VENDOR_SPECIFIC_INFO 0xDD #define WLAN_EID_COUNTRY 7 +#define WLAN_EID_RSN_INFO 48 +#define RSN_CAPABILITY_MFP_REQ (1 << 6) #endif dbus_message_iter_recurse(iter, &array); @@ -2227,15 +3031,47 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) bss->wps_capabilities = 0; bss->keymgmt = 0; - memset(bss->country_code, 0, COUNTRY_CODE_LENGTH); for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end; ie += ie[1] + 2) { #if defined TIZEN_EXT unsigned char *vsie; int vsie_len = 0; - if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) { - SUPPLICANT_DBG("IE: match vendor specific data"); + + if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) { + SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode"); + +/* + Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode + Tag Number: Vendor Specific (221) -> ie[0] + Tag length: 26 -> ie[1] + OUI: 50:6f:9a (Wi-Fi Alliance) -> ie[2] + Vendor Specific OUI Type: 28 -> ie[5] + BSSID: 92:fd:f0:20:2b:09 -> ie[6] + SSID length: 15 -> ie[12] + SSID: Wi-Fi-5.2.3-owe -> ie[13] + +0000 dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d ..Po..... +..Wi- +0010 46 69 2d 35 2e 32 2e 33 2d 6f 77 65 Fi-5.2.3-owe + +*/ + bss->owe_transition_mode = TRUE; + if (ie[1] >= 11) { // Tag length is at least up to ssid length position. + memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX); + if (ie[12] > 0 && ie[12] < 32) { + memcpy(bss->transition_mode_ssid, ie+13, ie[12]); + bss->transition_mode_ssid_len = ie[12]; + } else + bss->transition_mode_ssid_len = 0; + } else + bss->owe_transition_mode = FALSE; + continue; + } + + if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) { + + if (!simplified_log) + SUPPLICANT_DBG("IE: match vendor specific data"); vsie_len = ie[1]+2; // tag number size(1), tag length size(1) vsie = (unsigned char *)g_try_malloc0(vsie_len); @@ -2248,13 +3084,63 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) continue; } - if(ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) { + if (ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) { /* Add country code only if it is a valid alphabet */ if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) { memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH); continue; } } + + if (ie[0] == WLAN_EID_HT_CAP && ie[1]) { + ht = true; + continue; + } + + if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) { + vht = true; + continue; + } + + if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) { + r_len = ie[1]; + rates = g_malloc0(r_len); + if (!rates) + continue; + + for (j = 0; ie && j < r_len; j++) { + rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000; + if (max_rate < rates[j]) + max_rate = rates[j]; + } + continue; + } + + if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) { + r_len = ie[1]; + ext_rates = g_malloc0(r_len); + if (!ext_rates) + continue; + + for (j = 0; ie && j < r_len; j++) { + ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000; + if (max_ext_rate < ext_rates[j]) + max_ext_rate = ext_rates[j]; + } + continue; + } + + if (ie[0] == WLAN_EID_RSN_INFO && ie[1] >= 20) { + r_len = ie[1]; + offset = 10 + ie[8] * 4; + offset += ie[offset] * 4 + 2; + + if (offset <= r_len + 1 && + (ie[offset] & RSN_CAPABILITY_MFP_REQ) != 0) + bss->pmf_required = TRUE; + + continue; + } #endif if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN || memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) @@ -2290,6 +3176,13 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities); } +#ifdef TIZEN_EXT + get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data); + if (rates) + g_free(rates); + if (ext_rates) + g_free(ext_rates); +#endif } static void bss_compute_security(struct g_supplicant_bss *bss) @@ -2336,24 +3229,32 @@ static void bss_compute_security(struct g_supplicant_bss *bss) bss->psk = TRUE; #endif -#if defined TIZEN_EXT_WIFI_MESH +#if defined TIZEN_EXT if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE) bss->sae = TRUE; + if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE) + bss->owe = TRUE; + if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_DPP) + bss->dpp = TRUE; #endif if (bss->ieee8021x) bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; +#if defined TIZEN_EXT + else if (bss->ft_ieee8021x) + bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; + else if (bss->sae) + bss->security = G_SUPPLICANT_SECURITY_SAE; +#endif else if (bss->psk) bss->security = G_SUPPLICANT_SECURITY_PSK; #if defined TIZEN_EXT else if (bss->ft_psk) bss->security = G_SUPPLICANT_SECURITY_FT_PSK; - else if (bss->ft_ieee8021x == TRUE) - bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; -#endif -#if defined TIZEN_EXT_WIFI_MESH - else if (bss->sae) - bss->security = G_SUPPLICANT_SECURITY_SAE; + else if (bss->owe || bss->owe_transition_mode) + bss->security = G_SUPPLICANT_SECURITY_OWE; + else if (bss->dpp) + bss->security = G_SUPPLICANT_SECURITY_DPP; #endif else if (bss->privacy) bss->security = G_SUPPLICANT_SECURITY_WEP; @@ -2369,7 +3270,9 @@ static void bss_property(const char *key, DBusMessageIter *iter, if (!bss->interface) return; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG("key %s", key); if (!key) @@ -2461,6 +3364,17 @@ static void bss_property(const char *key, DBusMessageIter *iter, dbus_bool_t hs20 = FALSE; dbus_message_iter_get_basic(iter, &hs20); bss->hs20 = hs20; + } else if (g_strcmp0(key, "SNR") == 0) { + dbus_int16_t snr = 0; + + dbus_message_iter_get_basic(iter, &snr); + bss->snr = snr; + } else if (g_strcmp0(key, "EstThroughput") == 0) { + dbus_uint32_t est_throughput = 0; + + dbus_message_iter_get_basic(iter, &est_throughput); + if (est_throughput != 0) + bss->est_throughput = est_throughput; #endif } else if (g_strcmp0(key, "IEs") == 0) bss_process_ies(iter, bss); @@ -2476,7 +3390,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter, GSupplicantNetwork *network; struct g_supplicant_bss *bss; const char *path = NULL; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); dbus_message_iter_get_basic(iter, &path); @@ -2485,7 +3401,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter, if (g_strcmp0(path, "/") == 0) return NULL; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG("%s", path); network = g_hash_table_lookup(interface->bss_mapping, path); @@ -2510,7 +3428,9 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter, void *user_data) { struct g_supplicant_bss *bss; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); bss = interface_bss_added(iter, user_data); @@ -2520,7 +3440,15 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter, dbus_message_iter_next(iter); if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID) +#if defined TIZEN_EXT + { + g_free(bss->path); + g_free(bss); + return; + } +#else return; +#endif supplicant_dbus_property_foreach(iter, bss_property, bss); @@ -2533,7 +3461,9 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter, void *user_data) { struct g_supplicant_bss *bss; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); bss = interface_bss_added(iter, user_data); @@ -2542,7 +3472,7 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter, supplicant_dbus_property_get_all(bss->path, SUPPLICANT_INTERFACE ".BSS", - bss_property, bss, NULL); + bss_property, bss, bss); bss_compute_security(bss); if (add_or_replace_bss_to_network(bss) < 0) @@ -2555,10 +3485,22 @@ static void update_signal(gpointer key, gpointer value, struct g_supplicant_bss *bss = value; GSupplicantNetwork *network = user_data; +#if defined TIZEN_EXT + if (!network->best_bss || (network->best_bss == bss)) { + if (bss->signal > network->signal) { + network->signal = bss->signal; + network->best_bss = bss; + } + return; + } + + update_best_bss(network, bss, network->best_bss); +#else if (bss->signal > network->signal) { network->signal = bss->signal; network->best_bss = bss; } +#endif } static void update_network_signal(GSupplicantNetwork *network) @@ -2572,12 +3514,72 @@ static void update_network_signal(GSupplicantNetwork *network) SUPPLICANT_DBG("New network signal %d", network->signal); } +#if defined TIZEN_EXT +static gboolean last_connected_timeout(gpointer data) +{ + GSupplicantInterface *interface = data; + GSupplicantNetwork *current_network = interface->current_network; + + SUPPLICANT_DBG("Timeout last connected bss"); + + if (current_network && current_network->best_bss) { + if (compare_bssid(current_network->best_bss->bssid, interface->connected_bssid)) { + g_supplicant_network_set_last_connected_bssid(current_network, interface->connected_bssid); + callback_network_changed(current_network, "LastConnectedBSSID"); + } + } + + last_connected_bss_timeout = 0; + return FALSE; +} + +static void add_timer_for_last_connected(GSupplicantInterface *interface) +{ + GSupplicantNetwork *current_network = interface->current_network; + + if (interface->state == G_SUPPLICANT_STATE_COMPLETED) { + if (current_network) { + struct g_supplicant_bss *best_bss = current_network->best_bss; + + memcpy(interface->connected_bssid, best_bss->bssid, WIFI_BSSID_LEN_MAX); + + if (last_connected_bss_timeout) + g_source_remove(last_connected_bss_timeout); + + last_connected_bss_timeout = g_timeout_add_seconds(LAST_CONNECTED_TIMEOUT, + last_connected_timeout, interface); + + SUPPLICANT_DBG("Add timer for last connected bssid [" MACSTR "]", + MAC2STR(best_bss->bssid)); + } + } +} + +static void remove_timer_for_last_connected(GSupplicantInterface *interface) +{ + if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) { + if (last_connected_bss_timeout != 0) { + g_source_remove(last_connected_bss_timeout); + last_connected_bss_timeout = 0; + SUPPLICANT_DBG("Remove timer for last connected bss"); + } + } +} +#endif + static void interface_current_bss(GSupplicantInterface *interface, DBusMessageIter *iter) { GSupplicantNetwork *network; struct g_supplicant_bss *bss; const char *path; +#if defined TIZEN_EXT + char bssid_buff1[WIFI_BSSID_STR_LEN] = {0,}; + char bssid_buff2[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str1 = bssid_buff1; + char *bssid_str2 = bssid_buff2; + gboolean update = FALSE; +#endif dbus_message_iter_get_basic(iter, &path); if (g_strcmp0(path, "/") == 0) { @@ -2596,6 +3598,18 @@ static void interface_current_bss(GSupplicantInterface *interface, return; interface->current_network = network; +#if defined TIZEN_EXT + snprintf(bssid_str1, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bss->bssid)); + snprintf(bssid_str2, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(network->best_bss->bssid)); + + SUPPLICANT_DBG("current network [%p], Passed bss %s, best bss %s", + interface->current_network, bssid_str1, bssid_str2); + + if (network->frequency != bss->frequency) { + network->frequency = bss->frequency; + update = TRUE; + } +#endif if (bss != network->best_bss) { /* @@ -2613,9 +3627,19 @@ static void interface_current_bss(GSupplicantInterface *interface, network->signal = bss->signal; callback_network_changed(network, "Signal"); +#if defined TIZEN_EXT + update = FALSE; + } else { + update = TRUE; +#endif } } +#if defined TIZEN_EXT + if (update) + callback_network_changed(network, ""); +#endif + /* * wpa_s could notify about CurrentBSS in any state once * it got associated. It is not sure such notification will @@ -2637,6 +3661,9 @@ static void interface_current_bss(GSupplicantInterface *interface, case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: case G_SUPPLICANT_STATE_COMPLETED: callback_network_associated(network); +#if defined TIZEN_EXT + add_timer_for_last_connected(interface); +#endif break; } } @@ -2647,6 +3674,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data) GSupplicantNetwork *network; struct g_supplicant_bss *bss = NULL; const char *path = NULL; + bool is_current_network_bss = false; dbus_message_iter_get_basic(iter, &path); if (!path) @@ -2660,6 +3688,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data) if (network->best_bss == bss) { network->best_bss = NULL; network->signal = BSS_UNKNOWN_STRENGTH; + is_current_network_bss = true; } g_hash_table_remove(bss_mapping, path); @@ -2669,8 +3698,16 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data) update_network_signal(network); - if (g_hash_table_size(network->bss_table) == 0) + if (g_hash_table_size(network->bss_table) == 0) { g_hash_table_remove(interface->network_table, network->group); + } else { + if (is_current_network_bss && network->best_bss) +#if defined TIZEN_EXT + callback_network_changed(network, "CheckMultiBssidConnect"); +#else + callback_network_changed(network, ""); +#endif + } } static void set_config_methods(DBusMessageIter *iter, void *user_data) @@ -2685,7 +3722,9 @@ static void wps_property(const char *key, DBusMessageIter *iter, if (!interface) return; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG("key: %s", key); if (g_strcmp0(key, "ConfigMethods") == 0) { @@ -2708,6 +3747,21 @@ static void wps_property(const char *key, DBusMessageIter *iter, } +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +void g_supplicant_replace_config_file(const char *ifname, const char *config_file) +{ + if (!ifname) + return; + + if (!config_file) + return; + + SUPPLICANT_DBG("New {%s, %s}", ifname, config_file); + g_hash_table_replace(config_file_table, + g_strdup(ifname), g_strdup(config_file)); +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + static void interface_property(const char *key, DBusMessageIter *iter, void *user_data) { @@ -2715,7 +3769,9 @@ static void interface_property(const char *key, DBusMessageIter *iter, if (!interface) return; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG("%s", key); if (!key) { @@ -2764,7 +3820,18 @@ static void interface_property(const char *key, DBusMessageIter *iter, interface->state = string2state(str); callback_interface_state(interface); } - +#if defined TIZEN_EXT + switch (interface->state) { + case G_SUPPLICANT_STATE_COMPLETED: + add_timer_for_last_connected(interface); + break; + case G_SUPPLICANT_STATE_DISCONNECTED: + remove_timer_for_last_connected(interface); + break; + default: + break; + } +#endif if (interface->ap_create_in_progress) { if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) callback_ap_create_fail(interface); @@ -2849,12 +3916,18 @@ static void interface_property(const char *key, DBusMessageIter *iter, if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { dbus_message_iter_get_basic(iter, &reason_code); callback_disconnect_reason_code(interface, reason_code); +#if defined TIZEN_EXT + SUPPLICANT_DBG("reason code (%d)", reason_code); +#endif } } else if (g_strcmp0(key, "AssocStatusCode") == 0) { int status_code; if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { dbus_message_iter_get_basic(iter, &status_code); callback_assoc_status_code(interface, status_code); +#if defined TIZEN_EXT + SUPPLICANT_DBG("status code (%d)", status_code); +#endif } } else { SUPPLICANT_DBG("key %s type %c", @@ -2892,7 +3965,8 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter, /*Fixed : stucking in scanning state when scan failed*/ #if defined TIZEN_EXT - GSupplicantInterfaceCallback scan_callback; + GSupplicantInterfaceCallback scan_callback; + SUPPLICANT_DBG(""); #endif if (iter) @@ -2900,14 +3974,15 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter, interface); #if defined TIZEN_EXT - scan_callback = interface->scan_callback; + scan_callback = interface->scan_callback; + callback_scan_done(interface); #endif if (interface->scan_callback) interface->scan_callback(0, interface, interface->scan_data); #if defined TIZEN_EXT - if (interface->scan_callback == scan_callback) { + if (interface->scan_callback == scan_callback) { #endif interface->scan_callback = NULL; interface->scan_data = NULL; @@ -3121,7 +4196,9 @@ static void signal_interface_removed(const char *path, DBusMessageIter *iter) static void signal_interface_changed(const char *path, DBusMessageIter *iter) { GSupplicantInterface *interface; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); interface = g_hash_table_lookup(interface_table, path); @@ -3171,7 +4248,9 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter) static void signal_bss_added(const char *path, DBusMessageIter *iter) { GSupplicantInterface *interface; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); interface = g_hash_table_lookup(interface_table, path); @@ -3219,14 +4298,95 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter) interface_network_removed(iter, interface); } +#if defined TIZEN_EXT +void *copy_vsie_list(gconstpointer src, gpointer data) +{ + return g_strdup(src); +} +#endif + + +static void signal_sta_authorized(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + const char *addr = NULL; + + SUPPLICANT_DBG(""); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + dbus_message_iter_get_basic(iter, &addr); + if (!addr) + return; + + callback_sta_authorized(interface, addr); +} + +static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + const char *addr = NULL; + + SUPPLICANT_DBG(""); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + dbus_message_iter_get_basic(iter, &addr); + if (!addr) + return; + + callback_sta_deauthorized(interface, addr); +} + +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +static void signal_eap(const char *path, DBusMessageIter *iter) +{ + GSupplicantInterface *interface; + const char *str = NULL; + + SUPPLICANT_DBG("EAPOL_DEBUG callback eap signal"); + + interface = g_hash_table_lookup(interface_table, path); + if (!interface) + return; + + // TODO: Identify EAP fail condition, currently timeout is used for failure. + + dbus_message_iter_get_basic(iter, &str); + if (!str) + return; + + if (g_strcmp0("completion", str)) + return; + + dbus_message_iter_next(iter); + + dbus_message_iter_get_basic(iter, &str); + if (!str) + return; + + if (!g_strcmp0("success", str)) + callback_eap(interface, true); + else + callback_eap(interface, false); +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ static void signal_bss_changed(const char *path, DBusMessageIter *iter) { GSupplicantInterface *interface; GSupplicantNetwork *network; GSupplicantSecurity old_security; + unsigned int old_wps_capabilities; struct g_supplicant_bss *bss; +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); interface = g_hash_table_lookup(bss_mapping, path); @@ -3242,8 +4402,12 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) return; supplicant_dbus_property_foreach(iter, bss_property, bss); + #if defined TIZEN_EXT - network->frequency = bss->frequency; + if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) { + network->frequency = bss->frequency; + network->phy_mode = bss->phy_mode; + } #endif old_security = network->security; bss_compute_security(bss); @@ -3251,18 +4415,18 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) if (old_security != bss->security) { struct g_supplicant_bss *new_bss; - SUPPLICANT_DBG("New network security for %s", bss->ssid); + SUPPLICANT_DBG("New network security for %s with path %s", + bss->ssid, bss->path); - /* Security change policy: - * - we first copy the current bss into a new one with - * its own pointer (path) - * - we remove the current bss related network which will - * tell the plugin about such removal. This is done due - * to the fact that a security change means a group change - * so a complete network change. - * (current bss becomes invalid as well) - * - we add the new bss: it adds new network and tell the - * plugin about it. */ + /* + * Security change policy: + * - We first copy the current bss into a new one with + * its own pointer (path) + * - Clear the old bss pointer and remove the network completely + * if there are no more BSSs in the bss table. + * - The new bss will be added either to an existing network + * or an additional network will be created + */ new_bss = g_try_new0(struct g_supplicant_bss, 1); if (!new_bss) @@ -3271,23 +4435,46 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) memcpy(new_bss, bss, sizeof(struct g_supplicant_bss)); new_bss->path = g_strdup(bss->path); #if defined TIZEN_EXT - new_bss->vsie_list = NULL; + new_bss->vsie_list = g_slist_copy_deep(bss->vsie_list, copy_vsie_list, NULL); #endif - g_hash_table_remove(interface->network_table, network->group); + if (network->best_bss == bss) { + network->best_bss = NULL; + network->signal = BSS_UNKNOWN_STRENGTH; + } + + g_hash_table_remove(bss_mapping, path); + + g_hash_table_remove(interface->bss_mapping, path); + g_hash_table_remove(network->bss_table, path); + + update_network_signal(network); + + if (g_hash_table_size(network->bss_table) == 0) + g_hash_table_remove(interface->network_table, + network->group); if (add_or_replace_bss_to_network(new_bss) < 0) { - /* Remove entries in hash tables to handle the - * failure in add_or_replace_bss_to_network + /* + * Prevent a memory leak on failure in + * add_or_replace_bss_to_network */ - g_hash_table_remove(bss_mapping, path); - g_hash_table_remove(interface->bss_mapping, path); - g_hash_table_remove(network->bss_table, path); + SUPPLICANT_DBG("Failed to add bss %s to network table", + new_bss->path); + g_free(new_bss->path); + g_free(new_bss); } return; } + old_wps_capabilities = network->wps_capabilities; + + if (old_wps_capabilities != bss->wps_capabilities) { + network->wps_capabilities = bss->wps_capabilities; + callback_network_changed(network, "WPSCapabilities"); + } + #if defined TIZEN_EXT if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) { network->wps = TRUE; @@ -3314,22 +4501,28 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) * If the new signal is lower than the SSID signal, we need * to check for the new maximum. */ - if (bss->signal < network->signal) { - if (bss != network->best_bss) -#ifndef TIZEN_EXT - return; -#else - { +#if defined TIZEN_EXT + if (!update_best_bss(network, bss, network->best_bss)) { + if (bss != network->best_bss) { callback_network_changed(network, ""); return; } -#endif + + network->signal = bss->signal; + update_network_signal(network); + } +#else + if (bss->signal < network->signal) { + if (bss != network->best_bss) + return; + network->signal = bss->signal; update_network_signal(network); } else { network->signal = bss->signal; network->best_bss = bss; } +#endif SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid, network->signal); @@ -3425,7 +4618,7 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter) if (g_strcmp0(name, "success") == 0) interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS; - else if (g_strcmp0(name, "failed") == 0) + else if (g_strcmp0(name, "fail") == 0) interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL; else interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN; @@ -3461,56 +4654,6 @@ static void signal_power_off(const char *path, DBusMessageIter *iter) } #endif -static void signal_station_connected(const char *path, DBusMessageIter *iter) -{ - GSupplicantInterface *interface; - const char *sta_mac = NULL; - - SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH); - - if (callbacks_pointer->add_station == NULL) - return; - - if (g_strcmp0(path, "/") == 0) - return; - - interface = g_hash_table_lookup(interface_table, path); - if (interface == NULL) - return; - - dbus_message_iter_get_basic(iter, &sta_mac); - if (sta_mac == NULL) - return; - - SUPPLICANT_DBG("New station %s connected", sta_mac); - callbacks_pointer->add_station(sta_mac); -} - -static void signal_station_disconnected(const char *path, DBusMessageIter *iter) -{ - GSupplicantInterface *interface; - const char *sta_mac = NULL; - - SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH); - - if (callbacks_pointer->remove_station == NULL) - return; - - if (g_strcmp0(path, "/") == 0) - return; - - interface = g_hash_table_lookup(interface_table, path); - if (interface == NULL) - return; - - dbus_message_iter_get_basic(iter, &sta_mac); - if (sta_mac == NULL) - return; - - SUPPLICANT_DBG("Station %s disconnected", sta_mac); - callbacks_pointer->remove_station(sta_mac); -} - static void create_peer_identifier(GSupplicantPeer *peer) { const unsigned char test[ETH_ALEN] = {}; @@ -4278,6 +5421,8 @@ static struct { { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed }, { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added }, { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed }, + { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized", signal_sta_authorized }, + { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized", signal_sta_deauthorized }, { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed }, @@ -4287,9 +5432,6 @@ static struct { { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off }, #endif - { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected }, - { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected }, - { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found }, { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost", signal_peer_lost }, @@ -4314,6 +5456,10 @@ static struct { signal_mesh_peer_disconnected }, #endif +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap }, +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + { } }; @@ -4710,6 +5856,19 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data) DBUS_TYPE_STRING, &config_file); } +#ifdef TIZEN_EXT + if (data->driver && g_strstr_len(data->driver, strlen(data->driver), "nl80211")) { + supplicant_dbus_dict_append_basic(&dict, "MacAddr", + DBUS_TYPE_UINT32, &data->mac_addr); + + supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr", + DBUS_TYPE_UINT32, &data->preassoc_mac_addr); + + supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime", + DBUS_TYPE_UINT32, &data->random_mac_lifetime); + } +#endif /* TIZEN_EXT */ + #if defined TIZEN_EXT_WIFI_MESH if (data->is_mesh_interface) { if (data->parent_ifname) @@ -4724,6 +5883,53 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data) supplicant_dbus_dict_close(iter, &dict); } +#if defined TIZEN_EXT +static void interface_get_state(const char *key, DBusMessageIter *iter, + void *user_data) +{ + struct interface_create_data *data = user_data; + GSupplicantInterface *interface = NULL; + const char *str = NULL; + + SUPPLICANT_DBG("key[%s]", key); + + if (!data) { + SUPPLICANT_DBG("data is NULL"); + return; + } + + interface = data->interface; + if (!interface) { + SUPPLICANT_DBG("interface is NULL"); + return; + } + + if (iter) + dbus_message_iter_get_basic(iter, &str); + + if (str) { + if (string2state(str) != interface->state) + interface->state = string2state(str); + } + + if (interface->state == G_SUPPLICANT_STATE_DISABLED) + interface->ready = FALSE; + else + interface->ready = TRUE; + + SUPPLICANT_DBG("state %s (%d)", str, interface->state); + + if (data->callback) { + data->callback(0, interface, data->user_data); +#if defined TIZEN_EXT_WIFI_MESH + callback_mesh_support(interface); +#endif + } + + interface_create_data_free(data); +} +#endif + static void interface_get_result(const char *error, DBusMessageIter *iter, void *user_data) { @@ -4732,6 +5938,9 @@ static void interface_get_result(const char *error, const char *path = NULL; int err; +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); if (error) { @@ -4751,6 +5960,16 @@ static void interface_get_result(const char *error, goto done; } +#if defined TIZEN_EXT + data->interface = interface; + err = supplicant_dbus_property_get(path, + SUPPLICANT_INTERFACE ".Interface", + "State", interface_get_state, data, NULL); + + if (err == 0) + return; +#endif + if (data->callback) { data->callback(0, interface, data->user_data); #if !defined TIZEN_EXT @@ -4792,7 +6011,9 @@ done: static void interface_get_params(DBusMessageIter *iter, void *user_data) { struct interface_create_data *data = user_data; - +#if defined TIZEN_EXT + if (!simplified_log) +#endif SUPPLICANT_DBG(""); dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname); @@ -4844,7 +6065,7 @@ struct interface_mesh_peer_data { }; static void interface_mesh_change_peer_params(DBusMessageIter *iter, - void *user_data) + void *user_data) { struct interface_mesh_peer_data *data = user_data; @@ -4911,6 +6132,11 @@ int g_supplicant_interface_mesh_peer_change_status( int g_supplicant_interface_create(const char *ifname, const char *driver, const char *bridge, +#ifdef TIZEN_EXT + unsigned int mac_policy, + unsigned int preassoc_mac_policy, + unsigned int random_mac_lifetime, +#endif /* TIZEN_EXT */ GSupplicantInterfaceCallback callback, void *user_data) { @@ -4933,6 +6159,11 @@ int g_supplicant_interface_create(const char *ifname, const char *driver, data->driver = g_strdup(driver); data->bridge = g_strdup(bridge); data->callback = callback; +#ifdef TIZEN_EXT + data->mac_addr = mac_policy; + data->preassoc_mac_addr = preassoc_mac_policy; + data->random_mac_lifetime = random_mac_lifetime; +#endif /* TIZEN_EXT */ data->user_data = user_data; ret = supplicant_dbus_method_call(SUPPLICANT_PATH, @@ -4988,7 +6219,6 @@ static void interface_remove_params(DBusMessageIter *iter, void *user_data) &data->interface->path); } - int g_supplicant_interface_remove(GSupplicantInterface *interface, GSupplicantInterfaceCallback callback, void *user_data) @@ -5166,14 +6396,16 @@ static void interface_scan_params(DBusMessageIter *iter, void *user_data) DBUS_TYPE_STRING, &type); #if defined TIZEN_EXT - SUPPLICANT_DBG("[specific_scan] num_ssids %d", data->scan_params->num_ssids); - if (data->scan_params->num_ssids != 0) + SUPPLICANT_DBG("[specific_scan] num_ssids %d", + data->scan_params->num_ssids); #endif - supplicant_dbus_dict_append_array(&dict, "SSIDs", - DBUS_TYPE_STRING, - append_ssids, - data->scan_params); + if (data->scan_params->ssids) { + supplicant_dbus_dict_append_array(&dict, "SSIDs", + DBUS_TYPE_STRING, + append_ssids, + data->scan_params); + } supplicant_add_scan_frequency(&dict, add_scan_frequencies, data->scan_params); } else @@ -5313,6 +6545,104 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface, return ret; } +#if defined TIZEN_EXT +static void interface_signalpoll_result(const char *error, + DBusMessageIter *iter, void *user_data) +{ + struct interface_signalpoll_data *data = user_data; + int err = 0; + dbus_int32_t maxspeed = 0; + dbus_int32_t strength = 0; + dbus_int32_t snr = 0; + DBusMessageIter sub_iter, dict; + + if (error) { + err = -EIO; + SUPPLICANT_DBG("error: %s", error); + goto out; + } + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) { + err = -EINVAL; + SUPPLICANT_DBG("invalid reply"); + goto out; + } + + dbus_message_iter_recurse(iter, &sub_iter); + dbus_message_iter_recurse(&sub_iter, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + switch (dbus_message_iter_get_arg_type(&value)) { + case DBUS_TYPE_INT32: + if (g_strcmp0(key, "linkspeed") == 0) { + dbus_message_iter_get_basic(&value, &maxspeed); + SUPPLICANT_DBG("linkspeed = %d", maxspeed); + break; + } else if (g_strcmp0(key, "rssi") == 0) { + dbus_message_iter_get_basic(&value, &strength); + SUPPLICANT_DBG("Strength = %d", strength); + break; + } else if (g_strcmp0(key, "SNR") == 0) { + dbus_message_iter_get_basic(&value, &snr); + SUPPLICANT_DBG("SNR = %d", snr); + break; + } + } + dbus_message_iter_next(&dict); + } + +out: + if(data->callback) + data->callback(err, maxspeed, strength, snr, data->user_data); + + g_free(data->path); + dbus_free(data); +} + +int g_supplicant_interface_signalpoll(GSupplicantInterface *interface, + GSupplicantMaxSpeedCallback callback, + void *user_data) +{ + struct interface_signalpoll_data *data; + int ret; + + if (!interface) + return -EINVAL; + + if (!system_available) + return -EFAULT; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + + data->interface = interface; + data->path = g_strdup(interface->path); + data->callback = callback; + data->user_data = user_data; + + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface", "SignalPoll", + NULL, interface_signalpoll_result, data, + interface); + + if (ret < 0) { + g_free(data->path); + dbus_free(data); + } + + return ret; +} +#endif + static int parse_supplicant_error(DBusMessageIter *iter) { int err = -ECONNABORTED; @@ -5364,7 +6694,10 @@ static void interface_select_network_result(const char *error, #if defined TIZEN_EXT g_free(data->ssid->ssid); - g_free(data->ssid->passphrase); + g_free((char *)data->ssid->passphrase); + g_free((char *)data->ssid->connector); + g_free((char *)data->ssid->c_sign_key); + g_free((char *)data->ssid->net_access_key); #endif g_free(data->ssid); dbus_free(data); @@ -5453,7 +6786,10 @@ error: g_free(data->path); #if defined TIZEN_EXT g_free(data->ssid->ssid); - g_free(data->ssid->passphrase); + g_free((char *)data->ssid->passphrase); + g_free((char *)data->ssid->connector); + g_free((char *)data->ssid->c_sign_key); + g_free((char *)data->ssid->net_access_key); #endif g_free(data->ssid); g_free(data); @@ -5604,10 +6940,8 @@ static void add_network_security_tls(DBusMessageIter *dict, if (!ssid->private_key_path) return; -#if !defined TIZEN_EXT if (!ssid->private_key_passphrase) return; -#endif if (ssid->ca_cert_path) supplicant_dbus_dict_append_basic(dict, "ca_cert", @@ -5616,11 +6950,9 @@ static void add_network_security_tls(DBusMessageIter *dict, supplicant_dbus_dict_append_basic(dict, "private_key", DBUS_TYPE_STRING, &ssid->private_key_path); -#if !defined TIZEN_EXT supplicant_dbus_dict_append_basic(dict, "private_key_passwd", DBUS_TYPE_STRING, &ssid->private_key_passphrase); -#endif supplicant_dbus_dict_append_basic(dict, "client_cert", DBUS_TYPE_STRING, &ssid->client_cert_path); @@ -5673,7 +7005,9 @@ static void add_network_security_peap(DBusMessageIter *dict, } - if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) { + if(g_strcmp0(ssid->phase2_auth, "GTC") == 0 && g_strcmp0(ssid->eap, "ttls") == 0) + phase2_auth = g_strdup_printf("autheap=%s", ssid->phase2_auth); + else if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) { phase2_auth = g_strdup_printf("autheap=%s", ssid->phase2_auth + strlen("EAP-")); } else @@ -5912,15 +7246,81 @@ static void add_network_security_proto(DBusMessageIter *dict, g_free(proto); } -#if defined TIZEN_EXT_WIFI_MESH +#if defined TIZEN_EXT static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid) { - if (ssid->security != G_SUPPLICANT_SECURITY_SAE) + if (ssid->security != G_SUPPLICANT_SECURITY_SAE + && ssid->security != G_SUPPLICANT_SECURITY_OWE + && ssid->security != G_SUPPLICANT_SECURITY_DPP) return; supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32, &ssid->ieee80211w); } + +static void add_network_security_connector(DBusMessageIter *dict, GSupplicantSSID *ssid) +{ + if (ssid->connector && strlen(ssid->connector) > 0) { + const char *key = "dpp_connector"; + + supplicant_dbus_dict_append_basic(dict, + key, DBUS_TYPE_STRING, + &ssid->connector); + } +} + +static size_t convert_hexstr_to_bin(const char *hex_str, unsigned char **bin) +{ + unsigned char *bin_res = NULL; + unsigned int i, j, hex; + size_t hex_str_len; + + if (!hex_str || strlen(hex_str) == 0) + return 0; + + hex_str_len = strlen(hex_str); + bin_res = g_try_malloc0(hex_str_len / 2); + if (!bin_res) + return 0; + + j = 0; + for (i = 0; i < hex_str_len; i+=2) { + sscanf(hex_str + i, "%02x", &hex); + bin_res[j++] = hex; + } + + *bin = bin_res; + return hex_str_len / 2; +} + +static void add_network_security_c_sign_key(DBusMessageIter *dict, GSupplicantSSID *ssid) +{ + if (ssid->c_sign_key && strlen(ssid->c_sign_key) > 0) { + const char *key = "dpp_csign"; + unsigned char *bin_csign = NULL; + size_t bin_csign_len = convert_hexstr_to_bin(ssid->c_sign_key, &bin_csign); + if (bin_csign_len != 0) + supplicant_dbus_dict_append_fixed_array(dict, + key, DBUS_TYPE_BYTE, + &bin_csign, bin_csign_len); + g_free(bin_csign); + } +} + +static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplicantSSID *ssid) +{ + if (ssid->net_access_key && strlen(ssid->net_access_key) > 0) { + const char *key = "dpp_netaccesskey"; + unsigned char *bin_netaccesskey = NULL; + size_t bin_netaccesskey_len = convert_hexstr_to_bin(ssid->net_access_key, &bin_netaccesskey); + if (bin_netaccesskey_len != 0) + supplicant_dbus_dict_append_fixed_array(dict, + key, DBUS_TYPE_BYTE, + &bin_netaccesskey, bin_netaccesskey_len); + g_free(bin_netaccesskey); + } +} + #endif static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) @@ -5964,12 +7364,24 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) add_network_security_ciphers(dict, ssid); add_network_security_proto(dict, ssid); break; -#endif -#if defined TIZEN_EXT_WIFI_MESH case G_SUPPLICANT_SECURITY_SAE: - key_mgmt = "SAE"; + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK) + key_mgmt = "SAE WPA-PSK"; // WFA (WPA3 & WPA2 Mixed -> WPA2 only) + else + key_mgmt = "SAE"; add_network_security_psk(dict, ssid); break; + case G_SUPPLICANT_SECURITY_OWE: + key_mgmt = "OWE"; + add_network_security_ciphers(dict, ssid); + add_network_security_proto(dict, ssid); + break; + case G_SUPPLICANT_SECURITY_DPP: + key_mgmt = "DPP"; + add_network_security_connector(dict, ssid); + add_network_security_c_sign_key(dict, ssid); + add_network_security_net_access_key(dict, ssid); + break; #endif } @@ -6008,6 +7420,9 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) DBusMessageIter dict; struct interface_connect_data *data = user_data; GSupplicantSSID *ssid = data->ssid; +#if defined TIZEN_EXT + GSupplicantInterface *interface = data->interface; +#endif supplicant_dbus_dict_open(iter, &dict); @@ -6027,7 +7442,7 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) add_network_security(&dict, ssid); -#if defined TIZEN_EXT_WIFI_MESH +#if defined TIZEN_EXT add_network_ieee80211w(&dict, ssid); #endif @@ -6035,12 +7450,12 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) DBUS_TYPE_BYTE, &ssid->ssid, ssid->ssid_len); - supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid", - DBUS_TYPE_INT32, - &ssid->ignore_broadcast_ssid); - #if defined TIZEN_EXT - if (ssid->bssid) { + bool owe_transition_mode = FALSE; + if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE)) + owe_transition_mode = TRUE; + + if (ssid->bssid && !owe_transition_mode) { char *bssid = NULL; bssid = g_try_malloc0(18); if (bssid == NULL) { @@ -6049,14 +7464,15 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) return; } - if (ssid->bssid_for_connect_len) - snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x", - ssid->bssid_for_connect[0], ssid->bssid_for_connect[1], ssid->bssid_for_connect[2], - ssid->bssid_for_connect[3], ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]); - else - snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x", - ssid->bssid[0], ssid->bssid[1], ssid->bssid[2], - ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]); + if (ssid->bssid_for_connect_len) { + snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid_for_connect)); + memcpy(interface->add_network_bssid, ssid->bssid_for_connect, WIFI_BSSID_LEN_MAX); + } else { + snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid)); + memcpy(interface->add_network_bssid, ssid->bssid, WIFI_BSSID_LEN_MAX); + } + + SUPPLICANT_DBG("bssid [" MACSTR "]", MAC2STR(interface->add_network_bssid)); supplicant_dbus_dict_append_basic(&dict, "bssid", DBUS_TYPE_STRING, &bssid); @@ -6135,6 +7551,7 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data) dbus_free(data); return; } + #if defined TIZEN_EXT GSupplicantSSID *ssid = data->ssid; if (ssid->pin_wps != NULL) { @@ -6145,79 +7562,214 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data) return; } } -#endif - supplicant_dbus_method_call(data->interface->path, - SUPPLICANT_INTERFACE ".Interface.WPS", "Start", - interface_add_wps_params, - interface_wps_start_result, data, NULL); +#endif + supplicant_dbus_method_call(data->interface->path, + SUPPLICANT_INTERFACE ".Interface.WPS", "Start", + interface_add_wps_params, + interface_wps_start_result, data, NULL); +} + +static void wps_process_credentials(DBusMessageIter *iter, void *user_data) +{ + dbus_bool_t credentials = TRUE; + + SUPPLICANT_DBG(""); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials); +} + + +#if defined TIZEN_EXT +#define NETCONFIG_SERVICE "net.netconfig" +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi" + +struct dec_method_call_data { + struct interface_connect_data *data; + DBusPendingCall *pending_call; +}; + +static struct dec_method_call_data decrypt_request_data; + +static void crypt_method_call_cancel(void) +{ + if (decrypt_request_data.pending_call) { + dbus_pending_call_cancel(decrypt_request_data.pending_call); + dbus_pending_call_unref(decrypt_request_data.pending_call); + decrypt_request_data.pending_call = NULL; + } + + g_free(decrypt_request_data.data->path); + g_free(decrypt_request_data.data->ssid); + dbus_free(decrypt_request_data.data); + decrypt_request_data.data = NULL; +} + +static void decryption_request_reply(DBusPendingCall *call, + void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args; + char *out_data; + int ret; + struct interface_connect_data *data = user_data; + + SUPPLICANT_DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message); + dbus_error_free(&error); + ret = -EINVAL; + goto done; + } + + if (dbus_message_iter_init(reply, &args) == FALSE) { + SUPPLICANT_DBG("dbus_message_iter_init() failed"); + ret = -EINVAL; + goto done; + } + + dbus_message_iter_get_basic(&args, &out_data); + data->ssid->passphrase = g_strdup((const gchar *)out_data); + + ret = supplicant_dbus_method_call(data->interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, data, + data->interface); + +done: + if (ret < 0) { + SUPPLICANT_DBG("AddNetwork failed %d", ret); + callback_assoc_failed(decrypt_request_data.data->user_data); + g_free(data->path); + g_free(data->ssid->ssid); + g_free((char *)data->ssid->passphrase); + g_free((char *)data->ssid->connector); + g_free((char *)data->ssid->c_sign_key); + g_free((char *)data->ssid->net_access_key); + g_free(data->ssid); + dbus_free(data); + } + + dbus_message_unref(reply); + dbus_pending_call_unref(call); + + decrypt_request_data.pending_call = NULL; + decrypt_request_data.data = NULL; } -static void wps_process_credentials(DBusMessageIter *iter, void *user_data) +static int send_decryption_request(const char *passphrase, + struct interface_connect_data *data) { - dbus_bool_t credentials = TRUE; + DBusMessage *msg = NULL; + DBusPendingCall *call; - SUPPLICANT_DBG(""); + SUPPLICANT_DBG("Decryption request"); - dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials); -} + if (!passphrase) { + SUPPLICANT_DBG("Invalid parameter"); + return -EINVAL; + } + if (!connection) + return -EINVAL; -#if defined TIZEN_EXT -#define NETCONFIG_SERVICE "net.netconfig" -#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" -#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi" + msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase"); + if (!msg) + return -EINVAL; -struct dec_method_call_data { - struct interface_connect_data *data; - DBusPendingCall *pending_call; -}; +#if defined TIZEN_EXT + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID)) { + SUPPLICANT_DBG("Could not fulfill decryption request"); + return -ENOMEM; + } +#else + dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID); +#endif -static struct dec_method_call_data decrypt_request_data; + if (!dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT_USE_DEFAULT)) { + dbus_message_unref(msg); + return -EIO; + } -static void crypt_method_call_cancel(void) -{ - if (decrypt_request_data.pending_call) { - dbus_pending_call_cancel(decrypt_request_data.pending_call); - dbus_pending_call_unref(decrypt_request_data.pending_call); - decrypt_request_data.pending_call = NULL; + if (!call) { + dbus_message_unref(msg); + return -EIO; } - g_free(decrypt_request_data.data->path); - g_free(decrypt_request_data.data->ssid); - dbus_free(decrypt_request_data.data); - decrypt_request_data.data = NULL; + decrypt_request_data.pending_call = call; + decrypt_request_data.data = data; + + dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL); + dbus_message_unref(msg); + + SUPPLICANT_DBG("Decryption request succeeded"); + + return 0; } -static void decryption_request_reply(DBusPendingCall *call, +static void decrypt_conf_obj_reply(DBusPendingCall *call, void *user_data) { DBusMessage *reply; DBusError error; - DBusMessageIter args; + DBusMessageIter iter, dict; char *out_data; int ret; struct interface_connect_data *data = user_data; - SUPPLICANT_DBG(""); - reply = dbus_pending_call_steal_reply(call); dbus_error_init(&error); if (dbus_set_error_from_message(&error, reply)) { - SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message); + SUPPLICANT_DBG("decryption_conf_obj_reply() %s %s", error.name, error.message); dbus_error_free(&error); ret = -EINVAL; goto done; } - if (dbus_message_iter_init(reply, &args) == FALSE) { + if (dbus_message_iter_init(reply, &iter) == FALSE) { SUPPLICANT_DBG("dbus_message_iter_init() failed"); ret = -EINVAL; goto done; } - dbus_message_iter_get_basic(&args, &out_data); - data->ssid->passphrase = g_strdup((const gchar *)out_data); + dbus_message_iter_recurse(&iter, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) { + if (g_strcmp0(key, "connector") == 0) { + dbus_message_iter_get_basic(&value, &out_data); + data->ssid->connector = g_strdup((const gchar *)out_data); + SUPPLICANT_DBG("connector %s", data->ssid->connector); + } else if (g_strcmp0(key, "c_sign_key") == 0) { + dbus_message_iter_get_basic(&value, &out_data); + data->ssid->c_sign_key = g_strdup((const gchar *)out_data); + SUPPLICANT_DBG("c_sign_key %s", data->ssid->c_sign_key); + } else if (g_strcmp0(key, "net_access_key") == 0) { + dbus_message_iter_get_basic(&value, &out_data); + data->ssid->net_access_key = g_strdup((const gchar *)out_data); + SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key); + } + } + dbus_message_iter_next(&dict); + } ret = supplicant_dbus_method_call(data->interface->path, SUPPLICANT_INTERFACE ".Interface", "AddNetwork", @@ -6231,7 +7783,9 @@ done: callback_assoc_failed(decrypt_request_data.data->user_data); g_free(data->path); g_free(data->ssid->ssid); - g_free(data->ssid->passphrase); + g_free((char *)data->ssid->connector); + g_free((char *)data->ssid->c_sign_key); + g_free((char *)data->ssid->net_access_key); g_free(data->ssid); dbus_free(data); } @@ -6243,15 +7797,15 @@ done: decrypt_request_data.data = NULL; } -static int send_decryption_request(const char *passphrase, +static int send_decryption_conf_obj_request(GSupplicantSSID *ssid, struct interface_connect_data *data) { DBusMessage *msg = NULL; DBusPendingCall *call; - SUPPLICANT_DBG("Decryption request"); + SUPPLICANT_DBG("Decryption configuration object request"); - if (!passphrase) { + if (!ssid) { SUPPLICANT_DBG("Invalid parameter"); return -EINVAL; } @@ -6260,11 +7814,15 @@ static int send_decryption_request(const char *passphrase, return -EINVAL; msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH, - NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase"); + NETCONFIG_WIFI_INTERFACE, "DecryptConfObj"); if (!msg) return -EINVAL; - dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->connector, + DBUS_TYPE_INVALID); + dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->c_sign_key, + DBUS_TYPE_INVALID); + dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->net_access_key, DBUS_TYPE_INVALID); if (!dbus_connection_send_with_reply(connection, msg, @@ -6281,13 +7839,23 @@ static int send_decryption_request(const char *passphrase, decrypt_request_data.pending_call = call; decrypt_request_data.data = data; - dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL); + dbus_pending_call_set_notify(call, decrypt_conf_obj_reply, data, NULL); dbus_message_unref(msg); - SUPPLICANT_DBG("Decryption request succeeded"); + SUPPLICANT_DBG("Decrypt Conf Obj request succeeded"); return 0; } + +static bool is_valid_config_object(GSupplicantSSID *ssid) +{ + return ((ssid->connector && + g_strcmp0(ssid->connector, "") != 0) && + (ssid->c_sign_key && + g_strcmp0(ssid->c_sign_key, "") != 0) && + (ssid->net_access_key && + g_strcmp0(ssid->net_access_key, "") != 0)); +} #endif int g_supplicant_interface_connect(GSupplicantInterface *interface, @@ -6372,7 +7940,7 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, intf_data->user_data = user_data; intf_data->network_remove_in_progress = TRUE; network_remove(intf_data); - } else + } else { #if defined TIZEN_EXT if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0 && @@ -6383,13 +7951,19 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, ret = send_decryption_request(ssid->passphrase, data); if (ret < 0) SUPPLICANT_DBG("Decryption request failed %d", ret); + } else if (is_valid_config_object(ssid)) { + ret = send_decryption_conf_obj_request(ssid, data); + if (ret < 0) + SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret); + } else #endif - ret = supplicant_dbus_method_call(interface->path, - SUPPLICANT_INTERFACE ".Interface", "AddNetwork", - interface_add_network_params, - interface_add_network_result, data, - interface); + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, data, + interface); + } } if (ret < 0) { @@ -6447,6 +8021,14 @@ static void network_remove_result(const char *error, g_free(connect_data->path); dbus_free(connect_data); } + } else if (is_valid_config_object(data->ssid)) { + ret = send_decryption_conf_obj_request(data->ssid, connect_data); + if (ret < 0) { + SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret); + g_free(connect_data->ssid); + g_free(connect_data->path); + dbus_free(connect_data); + } } else #endif supplicant_dbus_method_call(data->interface->path, @@ -7039,6 +8621,7 @@ int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params, return -EINPROGRESS; } + static const char *g_supplicant_rule0 = "type=signal," "path=" DBUS_PATH_DBUS "," "sender=" DBUS_SERVICE_DBUS "," @@ -7085,7 +8668,65 @@ static void invoke_introspect_method(void) dbus_message_unref(message); } +#if defined TIZEN_EXT && defined TIZEN_EXT_INS +void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid, + bool last_connected_bssid, bool assoc_reject, bool signal_bssid, + unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score, + unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz) +{ + ins_settings.preferred_freq_bssid = preferred_freq_bssid; + ins_settings.last_connected_bssid = last_connected_bssid; + ins_settings.assoc_reject = assoc_reject; + ins_settings.signal_bssid = signal_bssid; + ins_settings.preferred_freq_bssid_score = preferred_freq_bssid_score; + ins_settings.last_connected_bssid_score = last_connected_bssid_score; + ins_settings.assoc_reject_score = assoc_reject_score; + ins_settings.signal_level3_5ghz = signal_level3_5ghz; + ins_settings.signal_level3_24ghz = signal_level3_24ghz; + + SUPPLICANT_DBG("preferred_freq_bssid [%s]", preferred_freq_bssid ? "true" : "false"); + SUPPLICANT_DBG("preferred_freq_bssid_score [%d]", preferred_freq_bssid_score); + SUPPLICANT_DBG("last_connected_bssid [%s]", last_connected_bssid ? "true" : "false"); + SUPPLICANT_DBG("last_connected_bssid_score [%d]", last_connected_bssid_score); + SUPPLICANT_DBG("assoc_reject [%s]", assoc_reject ? "true" : "false"); + SUPPLICANT_DBG("assoc_reject_score [%d]", assoc_reject_score); + SUPPLICANT_DBG("signal_bssid [%s]", signal_bssid ? "true" : "false"); + SUPPLICANT_DBG("signal_level3_5ghz [%d]", signal_level3_5ghz); + SUPPLICANT_DBG("signal_level3_24ghz [%d]", signal_level3_24ghz); +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ + +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb) +{ + SUPPLICANT_DBG("g_supplicant_register_eap_callback %p", cb); + + if (!callbacks_pointer) { + SUPPLICANT_DBG("callbacks_pointer is NULL"); + return; + } + + callbacks_pointer->eap = cb; +} + +void g_supplicant_unregister_eap_callback(void) +{ + SUPPLICANT_DBG("g_supplicant_unregister_eap_callback"); + + if (!callbacks_pointer) { + SUPPLICANT_DBG("callbacks_pointer is NULL"); + return; + } + + callbacks_pointer->eap = NULL; +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +int g_supplicant_register(GSupplicantCallbacks *callbacks) +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ int g_supplicant_register(const GSupplicantCallbacks *callbacks) +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ { connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); if (!connection) @@ -7097,7 +8738,9 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) connection = NULL; return -EIO; } - +#if defined TIZEN_EXT + simplified_log = connman_setting_get_bool("SimplifiedLog"); +#endif callbacks_pointer = callbacks; eap_methods = 0; @@ -7147,6 +8790,7 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) } else invoke_introspect_method(); + SUPPLICANT_DBG("supplicant dbus setup completed"); return 0; } @@ -7235,3 +8879,176 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks) callbacks_pointer = NULL; eap_methods = 0; } + +#ifdef TIZEN_EXT +struct supplicant_mac_policy { + GSupplicantMacPolicyCallback callback; + dbus_uint32_t policy; + const void *user_data; +}; + +static void mac_policy_result(const char *error, + DBusMessageIter *iter, void *user_data) +{ + struct supplicant_mac_policy *data = user_data; + int result = 0; + + if (!user_data) + return; + + if (error) { + SUPPLICANT_DBG("Mac policy setting failure %s", error); + result = -EINVAL; + } + + if (data->callback) + data->callback(result, data->policy, + (void *) data->user_data); + + dbus_free(data); +} + +static void mac_policy_params(DBusMessageIter *iter, void *user_data) +{ + struct supplicant_mac_policy *data = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy)); +} + +int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface, + GSupplicantMacPolicyCallback callback, + unsigned int policy, + void *user_data) +{ + struct supplicant_mac_policy *data = NULL; + int ret; + + if (!system_available) + return -EFAULT; + + if (!interface) + return -EINVAL; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + + data->callback = callback; + data->policy = policy; + data->user_data = user_data; + + ret = supplicant_dbus_property_set(interface->path, + SUPPLICANT_INTERFACE ".Interface", + "MacAddr", DBUS_TYPE_INT32_AS_STRING, + mac_policy_params, mac_policy_result, data, NULL); + if (ret < 0) { + SUPPLICANT_DBG("Unable to set MacAddr configuration"); + dbus_free(data); + } + + return ret; +} + +int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface, + GSupplicantMacPolicyCallback callback, + unsigned int policy, + void *user_data) +{ + struct supplicant_mac_policy *data; + int ret; + + if (!system_available) + return -EFAULT; + + if (!interface) + return -EINVAL; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + + data->callback = callback; + data->policy = policy; + data->user_data = user_data; + + ret = supplicant_dbus_property_set(interface->path, + SUPPLICANT_INTERFACE ".Interface", + "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING, + mac_policy_params, mac_policy_result, data, NULL); + if (ret < 0) { + SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration"); + dbus_free(data); + } + + return ret; +} + +struct supplicant_random_mac_lifetime { + GSupplicantRandomMaclifetimeCallback callback; + dbus_uint32_t lifetime; + const void *user_data; +}; + +static void random_mac_lifetime_result(const char *error, + DBusMessageIter *iter, void *user_data) +{ + struct supplicant_random_mac_lifetime *data = user_data; + int result = 0; + + if (!user_data) + return; + + if (error) { + SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error); + result = -EINVAL; + } + + if (data->callback) + data->callback(result, data->lifetime, + (void *) data->user_data); + + dbus_free(data); +} + +static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data) +{ + struct supplicant_random_mac_lifetime *data = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime)); +} + +int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface, + GSupplicantRandomMaclifetimeCallback callback, + unsigned int lifetime, + void *user_data) +{ + struct supplicant_random_mac_lifetime *data; + int ret; + + if (!system_available) + return -EFAULT; + + if (!interface) + return -EINVAL; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + + data->callback = callback; + data->lifetime = lifetime; + data->user_data = user_data; + + ret = supplicant_dbus_property_set(interface->path, + SUPPLICANT_INTERFACE ".Interface", + "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING, + random_mac_lifetime_params, random_mac_lifetime_result, + data, NULL); + if (ret < 0) { + SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration"); + dbus_free(data); + } + + return ret; +} +#endif