X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gsupplicant%2Fsupplicant.c;h=e457fef247429d0bf870f835674cd39da4f369c5;hb=00b8c314dc2cfb641494d413f4b00d90a10ecbeb;hp=2e8af6aeb783e58119befbaeaef1076a33222786;hpb=8460af05dcd14e095e5376e4e33f21819e9ae5e0;p=platform%2Fupstream%2Fconnman.git diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c old mode 100644 new mode 100755 index 2e8af6a..e457fef --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -40,6 +40,10 @@ #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 @@ -50,14 +54,29 @@ #define WLAN_EID_SUPP_RATES 1 #define WLAN_EID_EXT_SUPP_RATES 50 #define COUNTRY_CODE_LENGTH 2 -#define WIFI_BSSID_LEN_MAX 6 +#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; @@ -155,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; @@ -225,6 +266,10 @@ struct _GSupplicantInterface { 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; @@ -260,12 +305,19 @@ struct g_supplicant_bss { 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 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 }; @@ -294,6 +346,13 @@ struct _GSupplicantNetwork { 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 }; @@ -344,6 +403,11 @@ 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; @@ -373,11 +437,25 @@ struct interface_scan_data { }; #if defined TIZEN_EXT -struct g_connman_bssids { - unsigned char bssid[WIFI_BSSID_LEN_MAX]; - 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); @@ -589,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); @@ -838,6 +919,19 @@ static void callback_sta_deauthorized(GSupplicantInterface *interface, 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) @@ -971,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); @@ -1023,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); @@ -1202,6 +1313,24 @@ static void interface_capability(const char *key, DBusMessageIter *iter, 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; @@ -1293,6 +1422,14 @@ bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *inter 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) @@ -1464,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) @@ -1606,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) { @@ -1620,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, @@ -1716,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) @@ -1730,12 +1937,10 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network) return NULL; if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK || -#if defined TIZEN_EXT - network->best_bss->security == G_SUPPLICANT_SECURITY_SAE || - network->best_bss->security == G_SUPPLICANT_SECURITY_OWE || - network->best_bss->security == G_SUPPLICANT_SECURITY_DPP || -#endif /* TIZEN_EXT */ - 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 | @@ -1762,12 +1967,9 @@ bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network) if (network == NULL || network->best_bss == NULL) return 0; -#if defined TIZEN_EXT - if (network->best_bss->security == G_SUPPLICANT_SECURITY_SAE || - network->best_bss->security == G_SUPPLICANT_SECURITY_OWE || + if (network->best_bss->security == G_SUPPLICANT_SECURITY_OWE || network->best_bss->security == G_SUPPLICANT_SECURITY_DPP) return false; -#endif /* TIZEN_EXT */ if (network->best_bss->rsn_selected) { const char *mode = g_supplicant_network_get_enc_mode(network); @@ -1807,11 +2009,181 @@ void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network) return vsie_list; } +static bool compare_bssid(unsigned char *bssid_a, unsigned char *bssid_b) +{ + if (!memcmp(bssid_a, bssid_b, WIFI_BSSID_LEN_MAX)) + return true; + + return false; +} + +static gchar *convert_bssid_to_str(unsigned char *bssid) +{ + GString *bssid_str; + unsigned int i; + + bssid_str = g_string_sized_new(18); + if (!bssid_str) + return NULL; + + 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, ":"); + } + + return g_string_free(bssid_str, FALSE); +} + +#if defined TIZEN_EXT_INS +static void count_assoc_reject(gpointer data, gpointer user_data) +{ + time_t assoc_reject_time = GPOINTER_TO_INT(data); + struct assoc_count_data *assoc_count = user_data; + + if (assoc_reject_time > assoc_count->ref_time) + assoc_count->assoc_count++; +} + +static uint16_t get_assoc_reject_cnt(GHashTable *assoc_reject_table, unsigned char *bssid) +{ + gchar *bssid_str; + struct assoc_reject_data *assoc_data; + struct assoc_count_data assoc_count; + time_t curr_time; + struct tm* timeinfo; + + if (g_hash_table_size(assoc_reject_table) < 1) + return 0; + + if (!bssid) + return 0; + + if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) + return 0; + + bssid_str = convert_bssid_to_str(bssid); + if (!bssid_str) + return 0; + + assoc_data = g_hash_table_lookup(assoc_reject_table, bssid_str); + if (!assoc_data) { + g_free(bssid_str); + return 0; + } + + if (g_slist_length(assoc_data->reject_time_list) < 1) { + g_free(bssid_str); + return 0; + } + + /* 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; - GSList **list = (GSList **)user_data; + 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)); @@ -1825,7 +2197,25 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data) bssids->strength = 100; bssids->frequency = bss->frequency; - *list = g_slist_append(*list, bssids); + 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"); } @@ -1835,27 +2225,159 @@ 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->strength > entry_b->strength) + if (entry_a->ins_score > entry_b->ins_score) return -1; - if (entry_a->strength < entry_b->strength) + 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) { - GSList *bssid_list = NULL; + struct update_bssid_data bssid_data; if (g_hash_table_size(network->bss_table) < 1) return NULL; - g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_list); - bssid_list = g_slist_sort(bssid_list, cmp_bss); + 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 bssid_list; + return cloned_assoc_reject_table; } + #endif static void merge_network(GSupplicantNetwork *network) @@ -2092,7 +2614,63 @@ 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; @@ -2142,6 +2720,11 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) } #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) { @@ -2172,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); @@ -2191,12 +2779,19 @@ done: * 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); @@ -2400,11 +2995,13 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) 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 @@ -2422,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); @@ -2438,8 +3037,41 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) #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); @@ -2452,7 +3084,7 @@ 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); @@ -2497,6 +3129,18 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) } 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) @@ -2596,16 +3240,18 @@ static void bss_compute_security(struct g_supplicant_bss *bss) 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; - else if (bss->sae) - bss->security = G_SUPPLICANT_SECURITY_SAE; - else if (bss->owe) + else if (bss->owe || bss->owe_transition_mode) bss->security = G_SUPPLICANT_SECURITY_OWE; else if (bss->dpp) bss->security = G_SUPPLICANT_SECURITY_DPP; @@ -2624,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) @@ -2716,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); @@ -2731,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); @@ -2740,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); @@ -2765,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); @@ -2796,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); @@ -2818,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) @@ -2835,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) { @@ -2859,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) { /* @@ -2876,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 @@ -2900,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; } } @@ -2958,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) { @@ -2981,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) { @@ -2988,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) { @@ -3037,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); @@ -3122,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", @@ -3396,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); @@ -3446,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); @@ -3531,12 +4335,46 @@ static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter) if (!interface) return; - dbus_message_iter_get_basic(iter, &addr); - if (!addr) + 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; - callback_sta_deauthorized(interface, addr); + 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) { @@ -3546,6 +4384,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) 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); @@ -3563,8 +4404,10 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) supplicant_dbus_property_foreach(iter, bss_property, bss); #if defined TIZEN_EXT - network->frequency = bss->frequency; - network->phy_mode = bss->phy_mode; + 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); @@ -3658,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); @@ -4607,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 */ + { } }; @@ -4935,7 +5788,7 @@ static void interface_create_result(const char *error, SUPPLICANT_DBG(""); if (error) { - g_message("error %s", error); + g_warning("error %s", error); err = -EIO; goto done; } @@ -5003,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) @@ -5017,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) { @@ -5025,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) { @@ -5044,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 @@ -5085,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); @@ -5204,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) { @@ -5226,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, @@ -5281,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) @@ -5616,6 +6553,7 @@ static void interface_signalpoll_result(const char *error, int err = 0; dbus_int32_t maxspeed = 0; dbus_int32_t strength = 0; + dbus_int32_t snr = 0; DBusMessageIter sub_iter, dict; if (error) { @@ -5624,7 +6562,12 @@ static void interface_signalpoll_result(const char *error, goto out; } - dbus_message_iter_get_arg_type(iter); + 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); @@ -5647,6 +6590,10 @@ static void interface_signalpoll_result(const char *error, 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); @@ -5654,7 +6601,7 @@ static void interface_signalpoll_result(const char *error, out: if(data->callback) - data->callback(err, maxspeed, strength, data->user_data); + data->callback(err, maxspeed, strength, snr, data->user_data); g_free(data->path); dbus_free(data); @@ -5993,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", @@ -6005,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); @@ -6422,7 +7365,10 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) add_network_security_proto(dict, ssid); break; 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: @@ -6474,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); @@ -6502,7 +7451,11 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) ssid->ssid_len); #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) { @@ -6511,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); @@ -6730,8 +7684,16 @@ static int send_decryption_request(const char *passphrase, if (!msg) return -EINVAL; +#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 if (!dbus_connection_send_with_reply(connection, msg, &call, DBUS_TIMEOUT_USE_DEFAULT)) { @@ -7002,7 +7964,7 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, interface_add_network_result, data, interface); } - } + } if (ret < 0) { g_free(data->path); @@ -7706,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) @@ -7718,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; @@ -7768,6 +8790,7 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) } else invoke_introspect_method(); + SUPPLICANT_DBG("supplicant dbus setup completed"); return 0; } @@ -7856,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