X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Fwifi.c;h=4280c478e2cce84417d48e9fdae6ac3cd3667c47;hb=00b8c314dc2cfb641494d413f4b00d90a10ecbeb;hp=fe753d757279af926f026087b7d7c48f17a95b36;hpb=0ea80470841d34bbfb20de9341f9f8932e5adea5;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/wifi.c b/plugins/wifi.c old mode 100644 new mode 100755 index fe753d7..4280c47 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -30,9 +30,8 @@ #include #include #include -#include -#include #include +#include #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -50,32 +49,61 @@ #include #include #include -#include #include #include #include #include #include +#include #include +#include "src/shared/util.h" + #define CLEANUP_TIMEOUT 8 /* in seconds */ #define INACTIVE_TIMEOUT 12 /* in seconds */ #define FAVORITE_MAXIMUM_RETRIES 2 -#define BGSCAN_DEFAULT "simple:30:-45:300" -#define AUTOSCAN_DEFAULT "exponential:3:300" +#define BGSCAN_DEFAULT "simple:30:-65:300" +#define AUTOSCAN_EXPONENTIAL "exponential:3:300" +#define AUTOSCAN_SINGLE "single:3" +#define SCAN_MAX_DURATION 10 #define P2P_FIND_TIMEOUT 30 #define P2P_CONNECTION_TIMEOUT 100 #define P2P_LISTEN_PERIOD 500 #define P2P_LISTEN_INTERVAL 2000 +#define ASSOC_STATUS_AUTH_TIMEOUT 16 #define ASSOC_STATUS_NO_CLIENT 17 +#if defined TIZEN_EXT +#define LOAD_SHAPING_MAX_RETRIES 7 +#else #define LOAD_SHAPING_MAX_RETRIES 3 +#endif #if defined TIZEN_EXT #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */ + + /* Wi-Fi Signal Strength (for 2.4G (dB)) + * Excellent : ~ -63 + * Good : -64 ~ -74 + * Weak : -75 ~ -82 + * Very weak : -83 ~ -88 + * No signal : -89 ~ + * + * Wi-Fi Signal Strength (for 5G (dB)) + * Excellent : ~ -67 + * Good : -68 ~ -76 + * Weak : -77 ~ -82 + * Very weak : -83 ~ -88 + * No signal : -89 ~ + */ +#define RSSI_LEVEL_2_5G -77 +#define RSSI_LEVEL_2_24G -75 +#define RSSI_LEVEL_3_5G -68 +#define RSSI_LEVEL_3_24G -64 +#define ROAM_SCAN_INTERVAL 60 /* 60 seconds */ #endif static struct connman_technology *wifi_technology = NULL; @@ -87,6 +115,12 @@ enum wifi_ap_capability{ WIFI_AP_NOT_SUPPORTED = 2, }; +enum wifi_scanning_type { + WIFI_SCANNING_UNKNOWN = 0, + WIFI_SCANNING_PASSIVE = 1, + WIFI_SCANNING_ACTIVE = 2, +}; + struct hidden_params { char ssid[32]; unsigned int ssid_len; @@ -147,7 +181,7 @@ struct wifi_data { * autoscan "emulation". */ struct autoscan_params *autoscan; - + enum wifi_scanning_type scanning_type; GSupplicantScanParams *scan_params; unsigned int p2p_find_timeout; unsigned int p2p_connection_timeout; @@ -160,6 +194,11 @@ struct wifi_data { int assoc_retry_count; struct connman_network *scan_pending_network; bool allow_full_scan; + unsigned int automaxspeed_timeout; + GSupplicantScanParams *hidden_scan_params; + unsigned int mac_policy; + unsigned int preassoc_mac_policy; + unsigned int mac_lifetime; #endif int disconnect_code; int assoc_code; @@ -169,6 +208,11 @@ struct wifi_data { #endif }; +struct disconnect_data { + struct wifi_data *wifi; + struct connman_network *network; +}; + #if defined TIZEN_EXT #include "connman.h" #include "dbus.h" @@ -178,17 +222,17 @@ struct wifi_data { static gboolean wifi_first_scan = false; static gboolean found_with_first_scan = false; static gboolean is_wifi_notifier_registered = false; +static GHashTable *failed_bssids = NULL; +static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, }; #endif - static GList *iface_list = NULL; static GList *pending_wifi_device = NULL; static GList *p2p_iface_list = NULL; -bool wfd_service_registered = false; +static bool wfd_service_registered = false; static void start_autoscan(struct connman_device *device); - static int tech_set_tethering(struct connman_technology *technology, const char *identifier, const char *passphrase, const char *bridge, bool enabled); @@ -1111,15 +1155,23 @@ static GSupplicantP2PServiceParams *fill_in_peer_service_params( if (version > 0) { params->version = version; - params->service = g_memdup(spec, spec_length); + if (spec_length > 0) { + params->service = g_malloc(spec_length); + memcpy(params->service, spec, spec_length); + } } else if (query_length > 0 && spec_length > 0) { - params->query = g_memdup(query, query_length); + params->query = g_malloc(query_length); + memcpy(params->query, query, query_length); params->query_length = query_length; - params->response = g_memdup(spec, spec_length); + params->response = g_malloc(spec_length); + memcpy(params->response, spec, spec_length); params->response_length = spec_length; } else { - params->wfd_ies = g_memdup(spec, spec_length); + if (spec_length > 0) { + params->wfd_ies = g_malloc(spec_length); + memcpy(params->wfd_ies, spec, spec_length); + } params->wfd_ies_length = spec_length; } @@ -1244,10 +1296,8 @@ static int peer_register_service(const unsigned char *specification, params = fill_in_peer_service_params(specification, specification_length, query, query_length, version); - if (!params) { - ret = -ENOMEM; + if (!params) continue; - } if (!found) { ret_f = g_supplicant_interface_p2p_add_service(iface, @@ -1332,10 +1382,8 @@ static int peer_unregister_service(const unsigned char *specification, params = fill_in_peer_service_params(specification, specification_length, query, query_length, version); - if (!params) { - ret = -ENOMEM; + if (!params) continue; - } ret = g_supplicant_interface_p2p_del_service(iface, params); if (ret != 0 && ret != -EINPROGRESS) @@ -1395,14 +1443,15 @@ static void wifi_newlink(unsigned flags, unsigned change, void *user_data) } if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) { - if (flags & IFF_LOWER_UP) { + if (flags & IFF_LOWER_UP) DBG("carrier on"); - - handle_tethering(wifi); - } else + else DBG("carrier off"); } + if (flags & IFF_LOWER_UP) + handle_tethering(wifi); + wifi->flags = flags; } @@ -1479,13 +1528,13 @@ static void reset_autoscan(struct connman_device *device) autoscan = wifi->autoscan; - if (autoscan->timeout == 0 && autoscan->interval == 0) + autoscan->interval = 0; + + if (autoscan->timeout == 0) return; g_source_remove(autoscan->timeout); - autoscan->timeout = 0; - autoscan->interval = 0; connman_device_unref(device); } @@ -1521,6 +1570,35 @@ static void check_p2p_technology(void) } } +struct last_connected { + GTimeVal modified; + gchar *ssid; + int freq; +}; + +static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data) +{ + GTimeVal *aval = (GTimeVal *)a; + GTimeVal *bval = (GTimeVal *)b; + + /* Note that the sort order is descending */ + if (aval->tv_sec < bval->tv_sec) + return 1; + + if (aval->tv_sec > bval->tv_sec) + return -1; + + return 0; +} + +static void free_entry(gpointer data) +{ + struct last_connected *entry = data; + + g_free(entry->ssid); + g_free(entry); +} + static void wifi_remove(struct connman_device *device) { struct wifi_data *wifi = connman_device_get_data(device); @@ -1544,7 +1622,7 @@ static void wifi_remove(struct connman_device *device) remove_pending_wifi_device(wifi); - if (wifi->p2p_find_timeout) { + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) { g_source_remove(wifi->p2p_find_timeout); connman_device_unref(wifi->device); } @@ -1552,6 +1630,13 @@ static void wifi_remove(struct connman_device *device) if (wifi->p2p_connection_timeout) g_source_remove(wifi->p2p_connection_timeout); +#if defined TIZEN_EXT + if (wifi->automaxspeed_timeout != 0) { + g_source_remove(wifi->automaxspeed_timeout); + wifi->automaxspeed_timeout = 0; + } +#endif + remove_networks(device, wifi); remove_peers(wifi); @@ -1566,6 +1651,16 @@ static void wifi_remove(struct connman_device *device) if (wifi->scan_params) g_supplicant_free_scan_params(wifi->scan_params); +#if defined TIZEN_EXT + if (wifi->hidden_scan_params) { + while (wifi->hidden_scan_params->ssids) { + struct scan_ssid *ssid; + ssid = wifi->hidden_scan_params->ssids->data; + wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid); + } + g_supplicant_free_scan_params(wifi->hidden_scan_params); + } +#endif g_free(wifi->autoscan); g_free(wifi->identifier); @@ -1691,12 +1786,25 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) { struct connman_config_entry **entries; GKeyFile *keyfile; +#if defined TIZEN_EXT + gchar **services = NULL; +#else gchar **services; +#endif /* defined TIZEN_EXT */ char *ssid, *name; int i, ret; bool value; int num_ssids = 0, add_param_failed = 0; +#if defined TIZEN_EXT + GSequenceIter *iter; + GSequence *latest_list; + struct last_connected *entry; + GTimeVal modified; + latest_list = g_sequence_new(free_entry); + if (!latest_list) + goto out; +#endif services = connman_storage_get_services(); for (i = 0; services && services[i]; i++) { if (strncmp(services[i], "wifi_", 5) != 0) @@ -1727,6 +1835,15 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) g_key_file_free(keyfile); continue; } + + gchar *str = g_key_file_get_string(keyfile, + services[i], "Modified", NULL); + if (!str) { + g_key_file_free(keyfile); + continue; + } + g_time_val_from_iso8601(str, &modified); + g_free(str); #endif ssid = g_key_file_get_string(keyfile, @@ -1735,6 +1852,22 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) name = g_key_file_get_string(keyfile, services[i], "Name", NULL); +#if defined TIZEN_EXT + entry = g_try_new(struct last_connected, 1); + if (!entry) { + g_sequence_free(latest_list); + g_free(ssid); + g_free(name); + g_key_file_free(keyfile); + goto out; + } + + entry->modified = modified; + entry->ssid = ssid; + + g_sequence_insert_sorted(latest_list, entry, + sort_entry, NULL); +#else ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name); if (ret < 0) add_param_failed++; @@ -1742,10 +1875,30 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) num_ssids++; g_free(ssid); +#endif g_free(name); g_key_file_free(keyfile); } +#if defined TIZEN_EXT + gint length = g_sequence_get_length(latest_list); + iter = g_sequence_get_begin_iter(latest_list); + + for (i = 0; i < length; i++) { + entry = g_sequence_get(iter); + + ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid); + if (ret < 0) + add_param_failed++; + else if (ret > 0) + num_ssids++; + + iter = g_sequence_iter_next(iter); + } + + g_sequence_free(latest_list); +out: +#endif /* * Check if there are any hidden AP that needs to be provisioned. */ @@ -1802,6 +1955,22 @@ static int get_hidden_connections_params(struct wifi_data *wifi, DBG("max ssids %d", driver_max_ssids); +#if defined TIZEN_EXT + if (!wifi->hidden_scan_params) { + wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!wifi->hidden_scan_params) + return 0; + + if (get_hidden_connections(wifi->hidden_scan_params) == 0) { + g_supplicant_free_scan_params(wifi->hidden_scan_params); + wifi->hidden_scan_params = NULL; + + return 0; + } + } + + orig_params = wifi->hidden_scan_params; +#else if (!wifi->scan_params) { wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); if (!wifi->scan_params) @@ -1816,12 +1985,17 @@ static int get_hidden_connections_params(struct wifi_data *wifi, } orig_params = wifi->scan_params; +#endif /* Let's transfer driver_max_ssids params */ for (i = 0; i < driver_max_ssids; i++) { struct scan_ssid *ssid; +#if defined TIZEN_EXT + if (!wifi->hidden_scan_params->ssids) +#else if (!wifi->scan_params->ssids) +#endif break; ssid = orig_params->ssids->data; @@ -1833,11 +2007,14 @@ static int get_hidden_connections_params(struct wifi_data *wifi, scan_params->num_ssids = i; scan_params->ssids = g_slist_reverse(scan_params->ssids); - scan_params->freqs = g_memdup(orig_params->freqs, - sizeof(uint16_t) * orig_params->num_freqs); - if (!scan_params->freqs) + if (orig_params->num_freqs <= 0) goto err; + scan_params->freqs = + g_malloc(sizeof(uint16_t) * orig_params->num_freqs); + memcpy(scan_params->freqs, orig_params->freqs, + sizeof(uint16_t) *orig_params->num_freqs); + scan_params->num_freqs = orig_params->num_freqs; } else @@ -1849,8 +2026,13 @@ static int get_hidden_connections_params(struct wifi_data *wifi, err: g_slist_free_full(scan_params->ssids, g_free); +#if defined TIZEN_EXT + g_supplicant_free_scan_params(wifi->hidden_scan_params); + wifi->hidden_scan_params = NULL; +#else g_supplicant_free_scan_params(wifi->scan_params); wifi->scan_params = NULL; +#endif return 0; } @@ -1868,10 +2050,12 @@ static int throw_wifi_scan(struct connman_device *device, if (wifi->tethering) return -EBUSY; + #if defined TIZEN_EXT - if (connman_device_get_scanning(device) && !wifi->allow_full_scan) + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI) + && !wifi->allow_full_scan) #else - if (connman_device_get_scanning(device)) + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) #endif return -EALREADY; @@ -1938,6 +2122,111 @@ static void service_state_changed(struct connman_service *service, break; } } + +static gboolean need_bss_transition(uint16_t freq, int snr, int strength) +{ + /* + * Since bssid->strength is a positive value, + * it need to be changed to its original value. + */ + int signal = strength - 120; + + /* + * If the currently connected AP matches the following conditions, + * scan for BSS transition is started. + * - SNR is less than 20 or RSSI level is less than 3 + */ + if (snr < 20 && snr != 0) + return TRUE; + else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G) + return TRUE; + else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G) + return TRUE; + + return FALSE; +} + +static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength) +{ + /* + * Since bssid->strength is a positive value, + * it need to be changed to its original value. + */ + int signal = strength - 120; + + /* + * If the AP that matches the following conditions exists in the SCAN result, + * BSS transition is started. + * - SNR is 25 or more and RSSI level is greater than 3 + */ + if (snr < 25 && snr != 0) + return FALSE; + + if (freq > 4900 && signal > RSSI_LEVEL_3_5G) + return TRUE; + else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G) + return TRUE; + + return FALSE; +} + +static void scan_callback_hidden(int result, + GSupplicantInterface *interface, void *user_data); + +static int network_disconnect(struct connman_network *network); + +static void start_roaming(struct wifi_data *wifi) +{ + bool roaming_ap_found = false; + GSList *bssid_list = NULL; + + if (!wifi || !wifi->network) + return; + + if (connman_setting_get_bool("WifiRoaming")) { + struct connman_network *network = wifi->network; + bssid_list = connman_network_get_bssid_list(network); + + if (g_slist_length(bssid_list) <= 1) + return; + + if (!connman_network_get_connected(network)) + return; + + if (connman_network_get_bool(network, "WiFi.Roaming")) + return; + + if (!need_bss_transition( + connman_network_get_frequency(network), + connman_network_get_snr(network), + connman_network_get_strength(network))) + return; + + for (bssid_list; bssid_list; bssid_list = bssid_list->next) { + struct g_connman_bssids *bssid = bssid_list->data; + + if (check_bss_condition(bssid->frequency, + bssid->score_snr, bssid->strength)) + roaming_ap_found = true; + } + + if (roaming_ap_found) { + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + + bssid = connman_network_get_bssid(network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", bssid_str); + + network_disconnect(network); + wifi->pending_network = network; + connman_network_set_bool(network, "WiFi.Roaming", true); + } + } +} + #endif static void scan_callback(int result, GSupplicantInterface *interface, @@ -1946,6 +2235,12 @@ static void scan_callback(int result, GSupplicantInterface *interface, struct connman_device *device = user_data; struct wifi_data *wifi = connman_device_get_data(device); bool scanning; +#if defined TIZEN_EXT + GSList *list = NULL; + bool favorite_exists = false; + struct connman_network *network = NULL; + struct connman_service *service = NULL; +#endif DBG("result %d wifi %p", result, wifi); @@ -1960,6 +2255,13 @@ static void scan_callback(int result, GSupplicantInterface *interface, g_supplicant_free_scan_params(wifi->scan_params); wifi->scan_params = NULL; } + +#if defined TIZEN_EXT + if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) { + g_supplicant_free_scan_params(wifi->hidden_scan_params); + wifi->hidden_scan_params = NULL; + } +#endif } if (result < 0) @@ -1986,25 +2288,46 @@ static void scan_callback(int result, GSupplicantInterface *interface, } #if defined TIZEN_EXT - if (wifi && wifi->allow_full_scan) { - int ret; - DBG("Trigger Full Channel Scan"); - wifi->allow_full_scan = FALSE; + if (wifi) { + for (list = wifi->networks; list; list = list->next) { + network = list->data; + service = connman_service_lookup_from_network(network); + + if (service != NULL && + (connman_service_get_favorite(service) == true) && + (connman_service_get_autoconnect(service) == true)) { + DBG("Favorite service exists [%s]", + connman_network_get_string(network, "Name")); + favorite_exists = true; + break; + } + } + } - ret = g_supplicant_interface_scan(wifi->interface, NULL, - scan_callback, device); - if (ret == 0) - return; + if (favorite_exists == false) { + if (wifi && wifi->allow_full_scan) { + int ret; + DBG("Trigger full channel scan"); + wifi->allow_full_scan = false; - /* On error, let's recall scan_callback, which will cleanup */ - return scan_callback(ret, interface, user_data); - } + ret = g_supplicant_interface_scan(wifi->interface, NULL, + scan_callback_hidden, device); + if (ret == 0) + return; + + /* On error, let's recall scan_callback, which will cleanup */ + return scan_callback(ret, interface, user_data); + } + } else + wifi->allow_full_scan = false; #endif - scanning = connman_device_get_scanning(device); - if (scanning) + scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI); + + if (scanning) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); + } if (result != -ENOLINK) #if defined TIZEN_EXT @@ -2023,12 +2346,18 @@ static void scan_callback(int result, GSupplicantInterface *interface, connman_device_unref(device); #if defined TIZEN_EXT - if (wifi && wifi->scan_pending_network && result != -EIO) { + if (!wifi) + goto done; + + if (wifi->scan_pending_network && result != -EIO) { network_connect(wifi->scan_pending_network); wifi->scan_pending_network = NULL; connman_network_set_connecting(wifi->network); + } else { + start_roaming(wifi); } +done: if (is_wifi_notifier_registered != true && wifi_first_scan == true && found_with_first_scan == true) { wifi_first_scan = false; @@ -2064,7 +2393,11 @@ static void scan_callback_hidden(int result, if (get_hidden_connections_params(wifi, scan_params) > 0) { ret = g_supplicant_interface_scan(wifi->interface, scan_params, +#if defined TIZEN_EXT + scan_callback, +#else scan_callback_hidden, +#endif device); if (ret == 0) return; @@ -2088,6 +2421,11 @@ static gboolean autoscan_timeout(gpointer data) autoscan = wifi->autoscan; +#if defined TIZEN_EXT + if (!autoscan) + return FALSE; +#endif + if (autoscan->interval <= 0) { interval = autoscan->base; goto set_interval; @@ -2103,6 +2441,21 @@ static gboolean autoscan_timeout(gpointer data) throw_wifi_scan(wifi->device, scan_callback_hidden); + /* + * In case BackgroundScanning is disabled, interval will reach the + * limit exactly after the very first passive scanning. It allows + * to ensure at most one passive scan is performed in such cases. + */ + if (!connman_setting_get_bool("BackgroundScanning") && + interval == autoscan->limit) { + g_source_remove(autoscan->timeout); + autoscan->timeout = 0; + + connman_device_unref(device); + + return FALSE; + } + set_interval: DBG("interval %d", interval); @@ -2149,19 +2502,25 @@ static struct autoscan_params *parse_autoscan_params(const char *params) int limit; int base; - DBG("Emulating autoscan"); + DBG(""); list_params = g_strsplit(params, ":", 0); if (list_params == 0) return NULL; - if (g_strv_length(list_params) < 3) { + if (!g_strcmp0(list_params[0], "exponential") && + g_strv_length(list_params) == 3) { + base = atoi(list_params[1]); + limit = atoi(list_params[2]); + } else if (!g_strcmp0(list_params[0], "single") && + g_strv_length(list_params) == 2) + base = limit = atoi(list_params[1]); + else { g_strfreev(list_params); return NULL; } - base = atoi(list_params[1]); - limit = atoi(list_params[2]); + DBG("Setup %s autoscanning", list_params[0]); g_strfreev(list_params); @@ -2180,10 +2539,50 @@ static struct autoscan_params *parse_autoscan_params(const char *params) static void setup_autoscan(struct wifi_data *wifi) { - if (!wifi->autoscan) - wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT); + /* + * If BackgroundScanning is enabled, setup exponential + * autoscanning if it has not been previously done. + */ + if (connman_setting_get_bool("BackgroundScanning")) { + wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL); + return; + } +#if defined TIZEN_EXT + else { + if (wifi->autoscan) { + g_free(wifi->autoscan); + wifi->autoscan = NULL; + } - start_autoscan(wifi->device); + DBG("BackgroundScanning is disabled"); + + return; + } +#else + + /* + * On the contrary, if BackgroundScanning is disabled, update autoscan + * parameters based on the type of scanning that is being performed. + */ + if (wifi->autoscan) { + g_free(wifi->autoscan); + wifi->autoscan = NULL; + } + + switch (wifi->scanning_type) { + case WIFI_SCANNING_PASSIVE: + /* Do not setup autoscan. */ + break; + case WIFI_SCANNING_ACTIVE: + /* Setup one single passive scan after active. */ + wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE); + break; + case WIFI_SCANNING_UNKNOWN: + /* Setup autoscan in this case but we should never fall here. */ + wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE); + break; + } +#endif } static void finalize_interface_creation(struct wifi_data *wifi) @@ -2197,20 +2596,22 @@ static void finalize_interface_creation(struct wifi_data *wifi) connman_device_set_powered(wifi->device, true); - if (!connman_setting_get_bool("BackgroundScanning")) - return; - if (wifi->p2p_device) return; - setup_autoscan(wifi); -} + if (!wifi->autoscan) + setup_autoscan(wifi); + + start_autoscan(wifi->device); +} static void interface_create_callback(int result, GSupplicantInterface *interface, void *user_data) { struct wifi_data *wifi = user_data; + char *bgscan_range_max; + long value; DBG("result %d ifname %s, wifi %p", result, g_supplicant_interface_get_ifname(interface), @@ -2226,6 +2627,24 @@ static void interface_create_callback(int result, wifi->interface_ready = true; finalize_interface_creation(wifi); } + + /* + * Set the BSS expiration age to match the long scanning + * interval to avoid the loss of unconnected networks between + * two scans. + */ + bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':'); + if (!bgscan_range_max || strlen(bgscan_range_max) < 1) + return; + + value = strtol(bgscan_range_max + 1, NULL, 10); + if (value <= 0 || errno == ERANGE) + return; + + if (g_supplicant_interface_set_bss_expiration_age(interface, + value + SCAN_MAX_DURATION) < 0) { + connman_warn("Failed to set bss expiration age"); + } } static int wifi_enable(struct connman_device *device) @@ -2233,7 +2652,7 @@ static int wifi_enable(struct connman_device *device) struct wifi_data *wifi = connman_device_get_data(device); int index; char *interface; - const char *driver = connman_option_get_string("wifi"); + const char *driver = connman_setting_get_string("wifi"); int ret; DBG("device %p %p", device, wifi); @@ -2247,6 +2666,11 @@ static int wifi_enable(struct connman_device *device) interface = connman_inet_ifname(index); ret = g_supplicant_interface_create(interface, driver, NULL, +#ifdef TIZEN_EXT + connman_device_get_mac_policy(device), + connman_device_get_preassoc_mac_policy(device), + connman_device_get_random_mac_lifetime(device), +#endif /* TIZEN_EXT */ interface_create_callback, wifi); g_free(interface); @@ -2273,22 +2697,35 @@ static int wifi_disable(struct connman_device *device) if (wifi->pending_network) wifi->pending_network = NULL; +#if !defined TIZEN_EXT stop_autoscan(device); +#endif - if (wifi->p2p_find_timeout) { + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) { g_source_remove(wifi->p2p_find_timeout); wifi->p2p_find_timeout = 0; connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false); connman_device_unref(wifi->device); } +#if defined TIZEN_EXT + if (wifi->automaxspeed_timeout != 0) { + g_source_remove(wifi->automaxspeed_timeout); + wifi->automaxspeed_timeout = 0; + } +#endif + /* In case of a user scan, device is still referenced */ - if (connman_device_get_scanning(device)) { + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); connman_device_unref(wifi->device); } +#if defined TIZEN_EXT + stop_autoscan(device); +#endif + remove_networks(device, wifi); remove_peers(wifi); @@ -2308,35 +2745,6 @@ static int wifi_disable(struct connman_device *device) return -EINPROGRESS; } -struct last_connected { - GTimeVal modified; - gchar *ssid; - int freq; -}; - -static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data) -{ - GTimeVal *aval = (GTimeVal *)a; - GTimeVal *bval = (GTimeVal *)b; - - /* Note that the sort order is descending */ - if (aval->tv_sec < bval->tv_sec) - return 1; - - if (aval->tv_sec > bval->tv_sec) - return -1; - - return 0; -} - -static void free_entry(gpointer data) -{ - struct last_connected *entry = data; - - g_free(entry->ssid); - g_free(entry); -} - static int get_latest_connections(int max_ssids, GSupplicantScanParams *scan_data) { @@ -2388,7 +2796,7 @@ static int get_latest_connections(int max_ssids, g_key_file_free(keyfile); continue; } - g_time_val_from_iso8601(str, &modified); + util_iso8601_to_timeval(str, &modified); g_free(str); ssid = g_key_file_get_string(keyfile, @@ -2402,6 +2810,9 @@ static int get_latest_connections(int max_ssids, g_sequence_free(latest_list); g_key_file_free(keyfile); g_free(ssid); +#if defined TIZEN_EXT + g_strfreev(services); +#endif return -ENOMEM; } @@ -2440,10 +2851,29 @@ static int get_latest_connections(int max_ssids, return num_ssids; } +static void wifi_update_scanner_type(struct wifi_data *wifi, + enum wifi_scanning_type new_type) +{ + DBG(""); + + if (!wifi || wifi->scanning_type == new_type) + return; + + wifi->scanning_type = new_type; + + setup_autoscan(wifi); +} + static int wifi_scan_simple(struct connman_device *device) { + struct wifi_data *wifi = connman_device_get_data(device); + reset_autoscan(device); + /* Distinguish between devices performing passive and active scanning */ + if (wifi) + wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE); + return throw_wifi_scan(device, scan_callback_hidden); } @@ -2463,7 +2893,7 @@ static gboolean p2p_find_stop(gpointer data) connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false); connman_device_unref(device); - reset_autoscan(device); + start_autoscan(device); return FALSE; } @@ -2536,19 +2966,22 @@ static void specific_scan_callback(int result, GSupplicantInterface *interface, struct wifi_data *wifi = connman_device_get_data(device); bool scanning; - DBG("result %d wifi %p", result, wifi); + DBG("result %d device %p wifi %p", result, device, wifi); if (wifi && wifi->scan_params) { g_supplicant_free_scan_params(wifi->scan_params); wifi->scan_params = NULL; } - scanning = connman_device_get_scanning(device); + scanning = connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI); if (scanning) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); connman_device_unref(device); } + + start_roaming(wifi); } static int wifi_specific_scan(enum connman_service_type type, @@ -2577,7 +3010,9 @@ static int wifi_specific_scan(enum connman_service_type type, if (wifi->tethering) return 0; - scanning = connman_device_get_scanning(device); + scanning = + connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI); if (scanning) return -EALREADY; @@ -2702,6 +3137,99 @@ static int wifi_specific_scan(enum connman_service_type type, return ret; } + +static void wifi_mac_policy_callback(int result, + unsigned int policy, + void *user_data) +{ + struct connman_device *device = user_data; + + if (result == 0) + connman_device_mac_policy_notify(device, result, policy); + + connman_device_unref(device); +} + +int wifi_set_mac_policy(struct connman_device *device, unsigned int policy) +{ + struct wifi_data *wifi = connman_device_get_data(device); + int ret; + + if (!wifi) + return -EINVAL; + + connman_device_ref(device); + + ret = g_supplicant_interface_set_mac_policy(wifi->interface, + wifi_mac_policy_callback, + policy, device); + if (ret != 0) + connman_device_unref(device); + + return ret; +} + +static void wifi_preassoc_mac_policy_callback(int result, + unsigned int policy, + void *user_data) +{ + struct connman_device *device = user_data; + + if (result == 0) + connman_device_preassoc_mac_policy_notify(device, result, policy); + + connman_device_unref(device); +} + +int wifi_set_preassoc_mac_policy(struct connman_device *device, unsigned int policy) +{ + struct wifi_data *wifi = connman_device_get_data(device); + int ret; + + if (!wifi) + return -EINVAL; + + connman_device_ref(device); + + ret = g_supplicant_interface_set_preassoc_mac_policy(wifi->interface, + wifi_preassoc_mac_policy_callback, + policy, device); + if (ret != 0) + connman_device_unref(device); + + return ret; +} + +static void wifi_random_mac_lifetime_callback(int result, + unsigned int lifetime, + void *user_data) +{ + struct connman_device *device = user_data; + + if (result == 0) + connman_device_random_mac_lifetime_notify(device, result, lifetime); + + connman_device_unref(device); +} + +int wifi_set_random_mac_lifetime(struct connman_device *device, unsigned int lifetime) +{ + struct wifi_data *wifi = connman_device_get_data(device); + int ret; + + if (!wifi) + return -EINVAL; + + connman_device_ref(device); + + ret = g_supplicant_interface_set_random_mac_lifetime(wifi->interface, + wifi_random_mac_lifetime_callback, + lifetime, device); + if (ret != 0) + connman_device_unref(device); + + return ret; +} #endif #if defined TIZEN_EXT_WIFI_MESH @@ -2714,7 +3242,8 @@ static void mesh_scan_callback(int result, GSupplicantInterface *interface, DBG("result %d wifi %p", result, wifi); - scanning = connman_device_get_scanning(device); + scanning = connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_MESH); if (scanning) connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_MESH, false); @@ -2733,7 +3262,7 @@ static int mesh_scan(struct connman_device *device) wifi = connman_device_get_data(device); - if (!wifi->mesh_interface) + if (!wifi || !wifi->mesh_interface) return -ENOTSUP; mesh_info = wifi->mesh_info; @@ -2778,7 +3307,8 @@ static int mesh_abort_scan(enum connman_service_type type, mesh_info = wifi->mesh_info; - scanning = connman_device_get_scanning(device); + scanning = connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_MESH); if (!scanning) return -EEXIST; @@ -2810,7 +3340,8 @@ static int mesh_specific_scan(enum connman_service_type type, mesh_info = wifi->mesh_info; - scanning = connman_device_get_scanning(device); + scanning = connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_MESH); if (scanning) return -EALREADY; @@ -2861,11 +3392,8 @@ static int mesh_specific_scan(enum connman_service_type type, * Note that the hidden scan is only used when connecting to this specific * hidden AP first time. It is not used when system autoconnects to hidden AP. */ -static int wifi_scan(enum connman_service_type type, - struct connman_device *device, - const char *ssid, unsigned int ssid_len, - const char *identity, const char* passphrase, - const char *security, void *user_data) +static int wifi_scan(struct connman_device *device, + struct connman_device_scan_params *params) { struct wifi_data *wifi = connman_device_get_data(device); GSupplicantScanParams *scan_params = NULL; @@ -2885,19 +3413,20 @@ static int wifi_scan(enum connman_service_type type, if (wifi->tethering) return -EBUSY; - if (type == CONNMAN_SERVICE_TYPE_P2P) + if (params->type == CONNMAN_SERVICE_TYPE_P2P) return p2p_find(device); #if defined TIZEN_EXT_WIFI_MESH - if (type == CONNMAN_SERVICE_TYPE_MESH) + if (params->type == CONNMAN_SERVICE_TYPE_MESH) return mesh_scan(device); #endif - DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid); + DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, + params->ssid); - scanning = connman_device_get_scanning(device); + scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI); - if (!ssid || ssid_len == 0 || ssid_len > 32) { + if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) { if (scanning) return -EALREADY; @@ -2926,8 +3455,8 @@ static int wifi_scan(enum connman_service_type type, return -ENOMEM; } - memcpy(scan_ssid->ssid, ssid, ssid_len); - scan_ssid->ssid_len = ssid_len; + memcpy(scan_ssid->ssid, params->ssid, params->ssid_len); + scan_ssid->ssid_len = params->ssid_len; scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid); scan_params->num_ssids = 1; @@ -2943,12 +3472,12 @@ static int wifi_scan(enum connman_service_type type, wifi->hidden = NULL; } - memcpy(hidden->ssid, ssid, ssid_len); - hidden->ssid_len = ssid_len; - hidden->identity = g_strdup(identity); - hidden->passphrase = g_strdup(passphrase); - hidden->security = g_strdup(security); - hidden->user_data = user_data; + memcpy(hidden->ssid, params->ssid, params->ssid_len); + hidden->ssid_len = params->ssid_len; + hidden->identity = g_strdup(params->identity); + hidden->passphrase = g_strdup(params->passphrase); + hidden->security = g_strdup(params->security); + hidden->user_data = params->user_data; wifi->hidden = hidden; if (scanning) { @@ -2962,7 +3491,7 @@ static int wifi_scan(enum connman_service_type type, } else if (wifi->connected) { g_supplicant_free_scan_params(scan_params); return wifi_scan_simple(device); - } else { + } else if (!params->force_full_scan) { ret = get_latest_connections(driver_max_ssids, scan_params); if (ret <= 0) { g_supplicant_free_scan_params(scan_params); @@ -2970,23 +3499,37 @@ static int wifi_scan(enum connman_service_type type, } } + /* Distinguish between devices performing passive and active scanning */ + wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE); + connman_device_ref(device); reset_autoscan(device); - +#if defined TIZEN_EXT + /* + * When doing a full scan, stored hidden networks also need to be scanned + * so that we can autoconnect to them. + */ + if (params->force_full_scan) + ret = g_supplicant_interface_scan(wifi->interface, scan_params, + scan_callback_hidden, device); + else +#endif ret = g_supplicant_interface_scan(wifi->interface, scan_params, scan_callback, device); - if (ret == 0) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, true); #if defined TIZEN_EXT - /*To allow the Full Scan after ssid based scan, set the flag here - It is required because Tizen does not use the ConnMan specific - backgroung Scan feature.Tizen has added the BG Scan feature in - net-config. To sync with up ConnMan, we need to issue the Full Scan - after SSID specific scan.*/ - wifi->allow_full_scan = TRUE; + /* + * To allow the Full Scan after ssid based scan, set the flag here + * It is required because Tizen does not use the ConnMan specific + * backgroung Scan feature.Tizen has added the BG Scan feature in + * net-config. To sync with up ConnMan, we need to issue the Full Scan + * after SSID specific scan. + */ + if (!params->force_full_scan && !do_hidden) + wifi->allow_full_scan = TRUE; #endif } else { g_supplicant_free_scan_params(scan_params); @@ -3001,6 +3544,24 @@ static int wifi_scan(enum connman_service_type type, return ret; } +static void wifi_stop_scan(enum connman_service_type type, + struct connman_device *device) +{ + struct wifi_data *wifi = connman_device_get_data(device); + + DBG("device %p wifi %p", device, wifi); + + if (!wifi) + return; + + if (type == CONNMAN_SERVICE_TYPE_P2P) { + if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) { + g_source_remove(wifi->p2p_find_timeout); + p2p_find_stop(device); + } + } +} + static void wifi_regdom_callback(int result, const char *alpha2, void *user_data) @@ -3040,9 +3601,13 @@ static struct connman_device_driver wifi_ng_driver = { .enable = wifi_enable, .disable = wifi_disable, .scan = wifi_scan, + .stop_scan = wifi_stop_scan, .set_regdom = wifi_set_regdom, #if defined TIZEN_EXT .specific_scan = wifi_specific_scan, + .set_mac_policy = wifi_set_mac_policy, + .set_preassoc_mac_policy = wifi_set_preassoc_mac_policy, + .set_random_mac_lifetime = wifi_set_random_mac_lifetime, #endif #if defined TIZEN_EXT_WIFI_MESH .abort_scan = mesh_abort_scan, @@ -3067,6 +3632,9 @@ static void system_killed(void) static int network_probe(struct connman_network *network) { +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("network %p", network); return 0; @@ -3111,7 +3679,8 @@ static void connect_callback(int result, GSupplicantInterface *interface, DBG("network %p result %d", network, result); #if defined TIZEN_EXT - set_connman_bssid(RESET_BSSID, NULL); + const char *ifname = g_supplicant_interface_get_ifname(interface); + set_connman_bssid(RESET_BSSID, NULL, ifname); for (list = iface_list; list; list = list->next) { wifi = list->data; @@ -3124,6 +3693,38 @@ static void connect_callback(int result, GSupplicantInterface *interface, return; found: + if (connman_network_get_bool(network, "WiFi.Roaming")) { + if (result < 0 ) { + connman_network_set_bool(network, "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + } else { + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + const char *cur_bssid; + + bssid = g_supplicant_interface_get_add_network_bssid(interface); + if (!bssid) { + connman_network_set_bool(network, "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + } else { + snprintf(bssid_str, + WIFI_BSSID_STR_LEN, + MACSTR, MAC2STR(bssid)); + + connman_network_set_string(network, + "WiFi.RoamingDstBSSID", bssid_str); + + cur_bssid = connman_network_get_string(network, + "WiFi.RoamingCurBSSID"); + + __connman_technology_notify_roaming_state(ifname, + "started", cur_bssid, bssid_str); + } + } + } #endif if (result == -ENOKEY) { connman_network_set_error(network, @@ -3155,6 +3756,12 @@ static GSupplicantSecurity network_security(const char *security) return G_SUPPLICANT_SECURITY_FT_PSK; else if (g_str_equal(security, "ft_ieee8021x") == TRUE) return G_SUPPLICANT_SECURITY_FT_IEEE8021X; + else if (g_str_equal(security, "sae")) + return G_SUPPLICANT_SECURITY_SAE; + else if (g_str_equal(security, "owe")) + return G_SUPPLICANT_SECURITY_OWE; + else if (g_str_equal(security, "dpp")) + return G_SUPPLICANT_SECURITY_DPP; #endif return G_SUPPLICANT_SECURITY_UNKNOWN; @@ -3200,8 +3807,12 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->scan_ssid = 1; security = connman_network_get_string(network, "WiFi.Security"); ssid->security = network_security(security); +#if defined TIZEN_EXT + ssid->ieee80211w = 1; +#endif ssid->passphrase = connman_network_get_string(network, "WiFi.Passphrase"); + ssid->eap = connman_network_get_string(network, "WiFi.EAP"); /* @@ -3244,20 +3855,21 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS"); ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS"); - #if defined TIZEN_EXT - ssid->bssid = connman_network_get_bssid(network); - - ssid->eap_keymgmt = network_eap_keymgmt( - connman_network_get_string(network, "WiFi.KeymgmtType")); - ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1"); - - if(g_strcmp0(ssid->eap, "fast") == 0) - ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE); + ssid->connector = connman_network_get_string(network, + "WiFi.Connector"); + ssid->c_sign_key = connman_network_get_string(network, + "WiFi.CSignKey"); + ssid->net_access_key = connman_network_get_string(network, + "WiFi.NetAccessKey"); +#endif - if (set_connman_bssid(CHECK_BSSID, NULL) == 6) { +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string( + connman_network_get_device(network), "Interface"); + if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) { ssid->bssid_for_connect_len = 6; - set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect); + set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname); DBG("BSSID : %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], @@ -3265,6 +3877,61 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) } else { ssid->freq = connman_network_get_frequency(network); } + + GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network); + if (bssid_list && g_slist_length(bssid_list) > 1) { + + /* If there are more than one bssid, + * the user-specified bssid is tried only once at the beginning. + * After that, the bssids in the list are tried in order. + */ + if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) { + set_connman_bssid(RESET_BSSID, NULL, ifname); + goto done; + } + + GSList *list; + char buff[MAC_ADDRESS_LENGTH]; + for (list = bssid_list; list; list = list->next) { + struct connman_bssids * bssids = (struct connman_bssids *)list->data; + + g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x", + bssids->bssid[0], bssids->bssid[1], bssids->bssid[2], + bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]); + buff[MAC_ADDRESS_LENGTH - 1] = '\0'; + + gchar *curr_bssid = g_strdup((const gchar *)buff); + + if (g_hash_table_contains(failed_bssids, curr_bssid)) { + DBG("bssid match, try next bssid"); + g_free(curr_bssid); + continue; + } else { + g_hash_table_add(failed_bssids, curr_bssid); + + memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX); + ssid->bssid = buff_bssid; + ssid->freq = (unsigned int)bssids->frequency; + break; + } + } + + if (!list) { + ssid->bssid = connman_network_get_bssid(network); + g_hash_table_remove_all(failed_bssids); + } + } else + ssid->bssid = connman_network_get_bssid(network); + +done: + ssid->eap_keymgmt = network_eap_keymgmt( + connman_network_get_string(network, "WiFi.KeymgmtType")); + ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1"); + + if (g_strcmp0(ssid->eap, "fast") == 0) + ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE); + + ssid->keymgmt = connman_network_get_keymgmt(network); #endif if (connman_setting_get_bool("BackgroundScanning")) @@ -3318,11 +3985,13 @@ static int network_connect(struct connman_network *network) static void disconnect_callback(int result, GSupplicantInterface *interface, void *user_data) { + struct disconnect_data *dd = user_data; + struct connman_network *network = dd->network; #if defined TIZEN_EXT GList *list; struct wifi_data *wifi; - struct connman_network *network = user_data; + g_free(dd); DBG("network %p result %d", network, result); for (list = iface_list; list; list = list->next) { @@ -3335,28 +4004,49 @@ static void disconnect_callback(int result, GSupplicantInterface *interface, goto found; } + if (connman_network_get_bool(wifi->network, "WiFi.Roaming")) + connman_network_set_bool(wifi->network, "WiFi.Roaming", false); + + if (network == wifi->pending_network) + wifi->pending_network = NULL; + /* wifi_data may be invalid because wifi is already disabled */ return; found: #else - struct wifi_data *wifi = user_data; + struct wifi_data *wifi = dd->wifi; + g_free(dd); #endif - DBG("result %d supplicant interface %p wifi %p", - result, interface, wifi); + DBG("result %d supplicant interface %p wifi %p networks: current %p " + "pending %p disconnected %p", result, interface, wifi, + wifi->network, wifi->pending_network, network); if (result == -ECONNABORTED) { DBG("wifi interface no longer available"); return; } - if (wifi->network) { - connman_network_set_connected(wifi->network, false); - wifi->network = NULL; - } +#if defined TIZEN_EXT + if (g_slist_find(wifi->networks, network) && + wifi->network != wifi->pending_network) +#else + if (g_slist_find(wifi->networks, network)) +#endif + connman_network_set_connected(network, false); wifi->disconnecting = false; + + if (network != wifi->network) { + if (network == wifi->pending_network) + wifi->pending_network = NULL; + DBG("current wifi network has changed since disconnection"); + return; + } + + wifi->network = NULL; + wifi->connected = false; if (wifi->pending_network) { @@ -3370,6 +4060,7 @@ found: static int network_disconnect(struct connman_network *network) { struct connman_device *device = connman_network_get_device(network); + struct disconnect_data *dd; struct wifi_data *wifi; int err; #if defined TIZEN_EXT @@ -3412,20 +4103,207 @@ static int network_disconnect(struct connman_network *network) wifi->disconnecting = true; -#if defined TIZEN_EXT - err = g_supplicant_interface_disconnect(wifi->interface, - disconnect_callback, network); -#else - err = g_supplicant_interface_disconnect(wifi->interface, - disconnect_callback, wifi); -#endif + dd = g_malloc0(sizeof(*dd)); + dd->wifi = wifi; + dd->network = network; - if (err < 0) + err = g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, dd); + if (err < 0) { wifi->disconnecting = false; + g_free(dd); + } return err; } +#if defined TIZEN_EXT +static void set_connection_mode(struct connman_network *network, + int linkspeed) +{ + ieee80211_modes_e phy_mode; + connection_mode_e conn_mode; + + phy_mode = connman_network_get_phy_mode(network); + switch (phy_mode) { + case IEEE80211_MODE_B: + if (linkspeed > 0 && linkspeed <= 11) + conn_mode = CONNECTION_MODE_IEEE80211B; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + case IEEE80211_MODE_BG: + if (linkspeed > 0 && linkspeed <= 11) + conn_mode = CONNECTION_MODE_IEEE80211B; + else if (linkspeed > 11 && linkspeed <= 54) + conn_mode = CONNECTION_MODE_IEEE80211G; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + case IEEE80211_MODE_BGN: + if (linkspeed > 0 && linkspeed <= 11) + conn_mode = CONNECTION_MODE_IEEE80211B; + else if (linkspeed > 11 && linkspeed <= 54) + conn_mode = CONNECTION_MODE_IEEE80211G; + else if (linkspeed > 54 && linkspeed <= 450) + conn_mode = CONNECTION_MODE_IEEE80211N; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + case IEEE80211_MODE_A: + if (linkspeed > 0 && linkspeed <= 54) + conn_mode = CONNECTION_MODE_IEEE80211A; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + case IEEE80211_MODE_AN: + if (linkspeed > 0 && linkspeed <= 54) + conn_mode = CONNECTION_MODE_IEEE80211A; + else if (linkspeed > 54 && linkspeed <= 450) + conn_mode = CONNECTION_MODE_IEEE80211N; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + case IEEE80211_MODE_ANAC: + if (linkspeed > 0 && linkspeed <= 54) + conn_mode = CONNECTION_MODE_IEEE80211A; + else if (linkspeed > 54 && linkspeed <= 450) + conn_mode = CONNECTION_MODE_IEEE80211N; + else if (linkspeed > 450 && linkspeed <= 1300) + conn_mode = CONNECTION_MODE_IEEE80211AC; + else + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + + break; + default: + conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN; + break; + } + + DBG("connection mode(%d)", conn_mode); + connman_network_set_connection_mode(network, conn_mode); +} + +static void signalpoll_callback(int result, int maxspeed, int strength, + int snr, void *user_data) +{ + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + struct timespec curr_time = {0}; + __time_t roam_scan_time; + const char *interface = NULL; + struct connman_device *device; + struct connman_network *network = user_data; + GSupplicantNetwork *supplicant_network; + struct wifi_data *wifi; + uint16_t freq = connman_network_get_frequency(network); + const char *group = connman_network_get_group(network); + + if (result != 0) { + DBG("Failed to get maxspeed from signalpoll !"); + connman_network_unref(network); + return; + } + + device = connman_network_get_device(network); + if (device) + wifi = connman_device_get_data(device); + + if (group) { + supplicant_network = g_supplicant_interface_get_network(wifi->interface, group); + if (supplicant_network) { + g_supplicant_network_set_signal(supplicant_network, strength); + g_supplicant_network_set_bss_signal(supplicant_network, strength, snr); + } + } + + strength += 120; + if (strength > 100) + strength = 100; + + bssid = connman_network_get_bssid(network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + + DBG("network %p, bssid %s, freq %u, maxspeed %d, strength %d, snr %d", + network, bssid_str, freq, maxspeed, strength, snr); + + connman_network_set_strength(network, (uint8_t)strength); + connman_network_set_snr(network, snr); + connman_network_set_maxspeed(network, maxspeed); + set_connection_mode(network, maxspeed); + + if (connman_network_get_max_bssid_count(network) <= 1) + goto done; + + clock_gettime(CLOCK_MONOTONIC, &curr_time); + roam_scan_time = connman_network_get_roam_scan_time(network); + if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL) + goto done; + + if (device && need_bss_transition(freq, snr, strength)) { + + interface = connman_device_get_string(device, "Interface"); + __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL); + + if (connman_setting_get_bool("WifiRoamingScan") == false) + goto done; + + throw_wifi_scan(device, scan_callback); + connman_network_set_roam_scan_time(network, curr_time.tv_sec); + } + +done: + connman_network_unref(network); +} + +static int network_signalpoll(struct wifi_data *wifi) +{ + GSupplicantInterface *interface; + struct connman_network *network; + + if (!wifi || !wifi->network) + return -ENODEV; + + wifi->network = connman_network_ref(wifi->network); + + interface = wifi->interface; + network = wifi->network; + + DBG("network %p", network); + + return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network); +} + +static gboolean autosignalpoll_timeout(gpointer data) +{ + struct wifi_data *wifi = data; + + if (!wifi || !wifi->automaxspeed_timeout) { + DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!"); + return FALSE; + } + + int ret = network_signalpoll(wifi); + if (ret < 0) { + DBG("Fail to get max speed !!"); + wifi->automaxspeed_timeout = 0; + + if (wifi->network) + connman_network_unref(wifi->network); + + return FALSE; + } + + return TRUE; +} +#endif + static struct connman_network_driver network_driver = { .name = "wifi", .type = CONNMAN_NETWORK_TYPE_WIFI, @@ -3440,6 +4318,19 @@ static void interface_added(GSupplicantInterface *interface) { const char *ifname = g_supplicant_interface_get_ifname(interface); const char *driver = g_supplicant_interface_get_driver(interface); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + +#if defined TIZEN_EXT + bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface); +#endif + struct wifi_data *wifi; wifi = g_supplicant_interface_get_data(interface); @@ -3463,6 +4354,12 @@ static void interface_added(GSupplicantInterface *interface) } connman_device_set_powered(wifi->device, true); +#if defined TIZEN_EXT + connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported); + /* Max number of SSIDs supported by wlan chipset that can be scanned */ + int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface); + connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids); +#endif } static bool is_idle(struct wifi_data *wifi) @@ -3529,6 +4426,7 @@ static bool handle_wps_completion(GSupplicantInterface *interface, if (wps) { const unsigned char *ssid, *wps_ssid; unsigned int ssid_len, wps_ssid_len; + struct disconnect_data *dd; const char *wps_key; /* Checking if we got associated with requested @@ -3541,16 +4439,16 @@ static bool handle_wps_completion(GSupplicantInterface *interface, if (!wps_ssid || wps_ssid_len != ssid_len || memcmp(ssid, wps_ssid, ssid_len) != 0) { + dd = g_malloc0(sizeof(*dd)); + dd->wifi = wifi; + dd->network = network; + connman_network_set_associating(network, false); -#if defined TIZEN_EXT g_supplicant_interface_disconnect(wifi->interface, - disconnect_callback, wifi->network); - + disconnect_callback, dd); +#if defined TIZEN_EXT connman_network_set_bool(network, "WiFi.UseWPS", false); connman_network_set_string(network, "WiFi.PinWPS", NULL); -#else - g_supplicant_interface_disconnect(wifi->interface, - disconnect_callback, wifi); #endif return false; } @@ -3593,8 +4491,14 @@ static bool handle_wps_completion(GSupplicantInterface *interface, static bool handle_assoc_status_code(GSupplicantInterface *interface, struct wifi_data *wifi) { +#if defined TIZEN_EXT + if ((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING || + wifi->state == G_SUPPLICANT_STATE_AUTHENTICATING || + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) && +#else if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING && wifi->assoc_code == ASSOC_STATUS_NO_CLIENT && +#endif wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) { wifi->load_shaping_retries ++; return TRUE; @@ -3607,10 +4511,10 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, struct connman_network *network, struct wifi_data *wifi) { -#if defined TIZEN_EXT - const char *security; struct connman_service *service; +#if defined TIZEN_EXT + const char *security; if (wifi->connected) return false; @@ -3627,9 +4531,9 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) return false; #else - struct connman_service *service; - - if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) + if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) && + !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) && + (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT))) return false; if (wifi->connected) @@ -3659,38 +4563,108 @@ static bool handle_wifi_assoc_retry(struct connman_network *network, { const char *security; - if (!wifi->network || wifi->connected || wifi->disconnecting || - connman_network_get_connecting(network) != true) { - wifi->assoc_retry_count = 0; - return false; + if (!wifi->network || wifi->connected || wifi->disconnecting || + connman_network_get_connecting(network) != true) { + wifi->assoc_retry_count = 0; + return false; + } + + if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING && + wifi->state != G_SUPPLICANT_STATE_ASSOCIATING && + wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + security = connman_network_get_string(network, "WiFi.Security"); + if (security && g_str_equal(security, "ieee8021x") == true && + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) { + wifi->assoc_retry_count = 0; + + /* Honestly it's not an invalid-key error, + * however QA team recommends that the invalid-key error + * might be better to display for user experience. + */ + switch (wifi->state) { + case G_SUPPLICANT_STATE_AUTHENTICATING: + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL); + break; + case G_SUPPLICANT_STATE_ASSOCIATED: + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY); + break; + default: + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + break; + } + + return false; + } + + return true; +} + +static void handle_wifi_roaming_complete(struct connman_network *network) +{ + const char *cur_bssid; + const char *dst_bssid; + const char *ifname; + struct connman_device *device; + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + enum connman_ipconfig_type type; + enum connman_ipconfig_method method; + + if (!connman_setting_get_bool("WifiRoaming") || + !connman_network_get_bool(network, "WiFi.Roaming")) + return; + + device = connman_network_get_device(network); + if (device) { + ifname = connman_device_get_string(device, "Interface"); + cur_bssid = connman_network_get_string(network, + "WiFi.RoamingCurBSSID"); + dst_bssid = connman_network_get_string(network, + "WiFi.RoamingDstBSSID"); } - if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING && - wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) { - wifi->assoc_retry_count = 0; - return false; - } + if (device && ifname && cur_bssid && dst_bssid) { + __connman_technology_notify_roaming_state(ifname, + "success", cur_bssid, dst_bssid); + connman_network_set_bool(network, + "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + connman_network_set_string(network, + "WiFi.RoamingDstBSSID", NULL); - security = connman_network_get_string(network, "WiFi.Security"); - if (security && g_str_equal(security, "ieee8021x") == true && - wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { - wifi->assoc_retry_count = 0; - return false; - } + service = connman_service_lookup_from_network(network); + if (!service) + return; - if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) { - wifi->assoc_retry_count = 0; + ipconfig_ipv4 = __connman_service_get_ip4config(service); + if (!ipconfig_ipv4) { + connman_error("Service has no IPv4 configuration"); + return; + } - /* Honestly it's not an invalid-key error, - * however QA team recommends that the invalid-key error - * might be better to display for user experience. - */ - connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + type = __connman_ipconfig_get_config_type(ipconfig_ipv4); + if (type != CONNMAN_IPCONFIG_TYPE_IPV4) + return; - return false; - } + method = __connman_ipconfig_get_method(ipconfig_ipv4); + if (method != CONNMAN_IPCONFIG_METHOD_DHCP) + return; - return true; + connman_network_set_bool(network, "WiFi.RoamingDHCP", true); + + if (set_connected_dhcp(network) != 0) + connman_network_set_bool(network, "WiFi.RoamingDHCP", false); + } } #endif @@ -3700,6 +4674,15 @@ static void interface_state(GSupplicantInterface *interface) struct connman_device *device; struct wifi_data *wifi; GSupplicantState state = g_supplicant_interface_get_state(interface); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + bool wps; bool old_connected; @@ -3710,17 +4693,20 @@ static void interface_state(GSupplicantInterface *interface) if (!wifi) return; + device = wifi->device; + if (!device) + return; + if (state == G_SUPPLICANT_STATE_COMPLETED) { if (wifi->tethering_param) { g_free(wifi->tethering_param->ssid); g_free(wifi->tethering_param); wifi->tethering_param = NULL; } - } - device = wifi->device; - if (!device) - return; + if (wifi->tethering) + stop_autoscan(device); + } if (g_supplicant_interface_get_ready(interface) && !wifi->interface_ready) { @@ -3734,6 +4720,15 @@ static void interface_state(GSupplicantInterface *interface) switch (state) { case G_SUPPLICANT_STATE_SCANNING: +#if defined TIZEN_EXT + if (wifi->automaxspeed_timeout != 0) { + g_source_remove(wifi->automaxspeed_timeout); + wifi->automaxspeed_timeout = 0; + DBG("Remove signalpoll timer!!"); + } + + if (!connman_network_get_bool(wifi->network, "WiFi.Roaming")) +#endif if (wifi->connected) connman_network_set_connected(network, false); @@ -3746,7 +4741,9 @@ static void interface_state(GSupplicantInterface *interface) #else stop_autoscan(device); #endif - +#if defined TIZEN_EXT + if (!connman_network_get_bool(wifi->network, "WiFi.Roaming")) +#endif if (!wifi->connected) connman_network_set_associating(network, true); @@ -3762,12 +4759,25 @@ static void interface_state(GSupplicantInterface *interface) wifi->scan_pending_network = NULL; /* should be cleared scanning flag */ - bool scanning = connman_device_get_scanning(device); + bool scanning = connman_device_get_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI); if (scanning){ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); connman_device_unref(device); } + + if (!wifi->automaxspeed_timeout) { + DBG("Going to start signalpoll timer!!"); + int ret = network_signalpoll(wifi); + if (ret < 0) + DBG("Fail to get max speed !!"); + else + wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi); + } + + g_hash_table_remove_all(failed_bssids); + handle_wifi_roaming_complete(network); #else /* though it should be already stopped: */ stop_autoscan(device); @@ -3784,6 +4794,16 @@ static void interface_state(GSupplicantInterface *interface) break; case G_SUPPLICANT_STATE_DISCONNECTED: +#if defined TIZEN_EXT + connman_network_set_strength(network, 0); + connman_network_set_maxspeed(network, 0); + + if (wifi->automaxspeed_timeout != 0) { + g_source_remove(wifi->automaxspeed_timeout); + wifi->automaxspeed_timeout = 0; + DBG("Remove signalpoll timer!!"); + } +#endif /* * If we're in one of the idle modes, we have * not started association yet and thus setting @@ -3798,8 +4818,39 @@ static void interface_state(GSupplicantInterface *interface) if (is_idle(wifi)) break; +#if defined TIZEN_EXT + if (!wifi->connected && handle_assoc_status_code(interface, wifi)) { + const char *group = connman_network_get_group(network); + GSupplicantNetwork *supplicant_network; + GSList *bssid_list = NULL; + guint bssid_length = 0; + + if (group) { + supplicant_network = g_supplicant_interface_get_network(interface, group); + + connman_network_set_assoc_reject_table(network, + g_supplicant_network_clone_assoc_reject_table(supplicant_network)); + + g_supplicant_network_update_assoc_reject(interface, supplicant_network); + } + + bssid_list = (GSList *)connman_network_get_bssid_list(network); + if (bssid_list) + bssid_length = g_slist_length(bssid_list); + + if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) { + network_connect(network); + break; + } + + wifi->load_shaping_retries = 0; + } + + g_hash_table_remove_all(failed_bssids); +#else if (handle_assoc_status_code(interface, wifi)) break; +#endif /* If previous state was 4way-handshake, then * it's either: psk was incorrect and thus we retry @@ -3811,9 +4862,10 @@ static void interface_state(GSupplicantInterface *interface) /* See table 8-36 Reason codes in IEEE Std 802.11 */ switch (wifi->disconnect_code) { +#if defined TIZEN_EXT case 1: /* Unspecified reason */ /* Let's assume it's because we got blocked */ - +#endif case 6: /* Class 2 frame received from nonauthenticated STA */ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_BLOCKED); @@ -3832,14 +4884,16 @@ static void interface_state(GSupplicantInterface *interface) break; } - if(wifi->disconnect_code > 0){ + if (wifi->disconnect_code > 0){ DBG("Set disconnect reason code(%d)", wifi->disconnect_code); connman_network_set_disconnect_reason(network, wifi->disconnect_code); } #endif - connman_network_set_connected(network, false); - connman_network_set_associating(network, false); + if (network != wifi->pending_network) { + connman_network_set_connected(network, false); + connman_network_set_associating(network, false); + } wifi->disconnecting = false; start_autoscan(device); @@ -3906,6 +4960,15 @@ static void interface_removed(GSupplicantInterface *interface) { const char *ifname = g_supplicant_interface_get_ifname(interface); struct wifi_data *wifi; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + DBG("ifname %s", ifname); @@ -3974,6 +5037,15 @@ static void p2p_support(GSupplicantInterface *interface) { char dev_type[17] = {}; const char *hostname; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + DBG(""); @@ -4000,11 +5072,29 @@ static void p2p_support(GSupplicantInterface *interface) static void scan_started(GSupplicantInterface *interface) { +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + DBG(""); } static void scan_finished(GSupplicantInterface *interface) { +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + #if defined TIZEN_EXT struct wifi_data *wifi; bool is_associating = false; @@ -4041,6 +5131,15 @@ static void scan_finished(GSupplicantInterface *interface) static void ap_create_fail(GSupplicantInterface *interface) { +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); int ret; @@ -4065,8 +5164,6 @@ static void ap_create_fail(GSupplicantInterface *interface) g_free(wifi->tethering_param); wifi->tethering_param = NULL; } - - return; } static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network) @@ -4074,11 +5171,11 @@ static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network) unsigned char strength; strength = 120 + g_supplicant_network_get_signal(supplicant_network); - #if !defined TIZEN_EXT if (strength > 100) strength = 100; #endif + return strength; } @@ -4173,6 +5270,59 @@ static void mesh_peer_removed(GSupplicantNetwork *supplicant_network) } #endif + +#if defined TIZEN_EXT +static GSList *get_supported_security_list(unsigned int keymgmt, + bool owe_transition_mode, + GSupplicantNetwork *supplicant_network) +{ + GSList *sec_list = NULL; + dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network); + const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network); + + if (keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_EAP | + G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) + sec_list = g_slist_prepend (sec_list, "ieee8021x"); + else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP) + sec_list = g_slist_prepend (sec_list, "ft_ieee8021x"); + + if (sec_list) + return sec_list; + + if (keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_PSK | + G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) { + if (!g_strcmp0(enc_mode, "aes")) + sec_list = g_slist_prepend (sec_list, "rsn"); + else if (!g_strcmp0(enc_mode, "tkip")) + sec_list = g_slist_prepend (sec_list, "psk"); + else if (!g_strcmp0(enc_mode, "mixed")) { + sec_list = g_slist_prepend (sec_list, "psk"); + sec_list = g_slist_prepend (sec_list, "rsn"); + } + } else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK) + sec_list = g_slist_prepend (sec_list, "ft_psk"); + + if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE) + sec_list = g_slist_prepend (sec_list, "sae"); + if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode) + sec_list = g_slist_prepend (sec_list, "owe"); + if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP) + sec_list = g_slist_prepend (sec_list, "dpp"); + + if (sec_list) + return sec_list; + + if (privacy) + sec_list = g_slist_prepend (sec_list, "wep"); + else + sec_list = g_slist_prepend (sec_list, "none"); + + return sec_list; +} +#endif + static void network_added(GSupplicantNetwork *supplicant_network) { struct connman_network *network; @@ -4187,13 +5337,22 @@ static void network_added(GSupplicantNetwork *supplicant_network) bool wps_advertizing; #if defined TIZEN_EXT + bool owe_transition_mode; + const unsigned char *transition_mode_ssid; + const unsigned char *transition_mode_bssid; + unsigned int transition_mode_ssid_len; + unsigned int keymgmt; GSList *vsie_list = NULL; + GSList *sec_list = NULL; const unsigned char *country_code; + ieee80211_modes_e phy_mode; #endif mode = g_supplicant_network_get_mode(supplicant_network); identifier = g_supplicant_network_get_identifier(supplicant_network); - +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("%s", identifier); if (!g_strcmp0(mode, "adhoc")) @@ -4207,6 +5366,15 @@ static void network_added(GSupplicantNetwork *supplicant_network) #endif interface = g_supplicant_network_get_interface(supplicant_network); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + wifi = g_supplicant_interface_get_data(interface); name = g_supplicant_network_get_name(supplicant_network); security = g_supplicant_network_get_security(supplicant_network); @@ -4253,42 +5421,66 @@ static void network_added(GSupplicantNetwork *supplicant_network) DBG("vsie_list is NULL"); country_code = g_supplicant_network_get_countrycode(supplicant_network); connman_network_set_countrycode(network, country_code); + phy_mode = g_supplicant_network_get_phy_mode(supplicant_network); + connman_network_set_phy_mode(network, phy_mode); #endif connman_network_set_string(network, "WiFi.Security", security); connman_network_set_strength(network, calculate_strength(supplicant_network)); connman_network_set_bool(network, "WiFi.WPS", wps); + connman_network_set_bool(network, "WiFi.WPSAdvertising", + wps_advertizing); if (wps) { /* Is AP advertizing for WPS association? * If so, we decide to use WPS by default */ if (wps_ready && wps_pbc && - wps_advertizing) { + wps_advertizing) #if !defined TIZEN_EXT connman_network_set_bool(network, "WiFi.UseWPS", true); #else DBG("wps is activating by ap but ignore it."); #endif - } } connman_network_set_frequency(network, g_supplicant_network_get_frequency(supplicant_network)); + #if defined TIZEN_EXT + keymgmt = g_supplicant_network_get_keymgmt(supplicant_network); connman_network_set_bssid(network, g_supplicant_network_get_bssid(supplicant_network)); + owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network); + connman_network_set_bool(network, "WiFi.TRANSITION_MODE", owe_transition_mode); + if (owe_transition_mode) { + transition_mode_ssid = (unsigned char *)g_supplicant_network_get_transition_mode_ssid(supplicant_network, &transition_mode_ssid_len); + connman_network_set_blob(network, "WiFi.TRANSITION_MODE_SSID", + transition_mode_ssid, transition_mode_ssid_len); + transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network); + connman_network_set_transition_mode_bssid(network, transition_mode_bssid); + } + + sec_list = get_supported_security_list(keymgmt, + owe_transition_mode, supplicant_network); + + connman_network_set_sec_list(network, sec_list); connman_network_set_maxrate(network, g_supplicant_network_get_maxrate(supplicant_network)); connman_network_set_enc_mode(network, g_supplicant_network_get_enc_mode(supplicant_network)); connman_network_set_rsn_mode(network, g_supplicant_network_get_rsn_mode(supplicant_network)); - connman_network_set_keymgmt(network, - g_supplicant_network_get_keymgmt(supplicant_network)); + connman_network_set_bool(network, "WiFi.PMFRequired", + (bool)g_supplicant_network_is_pmf_required(supplicant_network)); + connman_network_set_keymgmt(network, keymgmt); connman_network_set_bool(network, "WiFi.HS20AP", g_supplicant_network_is_hs20AP(supplicant_network)); connman_network_set_bssid_list(network, (GSList *)g_supplicant_network_get_bssid_list(supplicant_network)); + connman_network_set_last_connected_bssid(network, + g_supplicant_network_get_last_connected_bssid(supplicant_network)); + connman_network_set_assoc_reject_table(network, + g_supplicant_network_clone_assoc_reject_table(supplicant_network)); #endif connman_network_set_available(network, true); connman_network_set_string(network, "WiFi.Mode", mode); @@ -4301,6 +5493,11 @@ static void network_added(GSupplicantNetwork *supplicant_network) connman_network_set_group(network, group); #if defined TIZEN_EXT + g_supplicant_network_set_last_connected_bssid(supplicant_network, + connman_network_get_last_connected_bssid(network)); +#endif + +#if defined TIZEN_EXT if (wifi_first_scan == true) found_with_first_scan = true; #endif @@ -4342,6 +5539,15 @@ static void network_removed(GSupplicantNetwork *network) #endif interface = g_supplicant_network_get_interface(network); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + wifi = g_supplicant_interface_get_data(interface); identifier = g_supplicant_network_get_identifier(network); name = g_supplicant_network_get_name(network); @@ -4379,6 +5585,7 @@ static void network_changed(GSupplicantNetwork *network, const char *property) struct wifi_data *wifi; const char *name, *identifier; struct connman_network *connman_network; + bool update_needed; #if defined TIZEN_EXT const unsigned char *bssid; @@ -4386,15 +5593,30 @@ static void network_changed(GSupplicantNetwork *network, const char *property) uint16_t frequency; bool wps; const unsigned char *country_code; + ieee80211_modes_e phy_mode; GSList *bssid_list; #endif interface = g_supplicant_network_get_interface(network); +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + wifi = g_supplicant_interface_get_data(interface); identifier = g_supplicant_network_get_identifier(network); name = g_supplicant_network_get_name(network); +#if defined TIZEN_EXT + if (!simplified_log) + DBG("name %s property %s", name, property); +#else DBG("name %s", name); +#endif if (!wifi) return; @@ -4403,17 +5625,82 @@ static void network_changed(GSupplicantNetwork *network, const char *property) if (!connman_network) return; - if (g_str_equal(property, "Signal")) { - connman_network_set_strength(connman_network, + if (g_str_equal(property, "WPSCapabilities")) { + bool wps; + bool wps_pbc; + bool wps_ready; + bool wps_advertizing; + + wps = g_supplicant_network_get_wps(network); + wps_pbc = g_supplicant_network_is_wps_pbc(network); + wps_ready = g_supplicant_network_is_wps_active(network); + wps_advertizing = + g_supplicant_network_is_wps_advertizing(network); + + connman_network_set_bool(connman_network, "WiFi.WPS", wps); + connman_network_set_bool(connman_network, + "WiFi.WPSAdvertising", wps_advertizing); + + if (wps) { + /* + * Is AP advertizing for WPS association? + * If so, we decide to use WPS by default + */ + if (wps_ready && wps_pbc && wps_advertizing) + connman_network_set_bool(connman_network, + "WiFi.UseWPS", true); + } + + update_needed = true; + } else if (g_str_equal(property, "Signal")) { + connman_network_set_strength(connman_network, calculate_strength(network)); - connman_network_update(connman_network); + update_needed = true; + } +#if defined TIZEN_EXT && defined TIZEN_EXT_INS + else if (g_str_equal(property, "LastConnectedBSSID")) { + const char *ident, *group; + char *service_ident; + bool need_save; + + ident = connman_device_get_ident(wifi->device); + group = connman_network_get_group(connman_network); + if (ident && group) { + service_ident = g_strdup_printf("%s_%s_%s", + __connman_network_get_type(connman_network), ident, group); + + need_save = connman_device_set_last_connected_ident(wifi->device, service_ident); + if (need_save) + connman_device_save_last_connected(wifi->device); + + g_free(service_ident); + } + + connman_network_set_last_connected_bssid(connman_network, + g_supplicant_network_get_last_connected_bssid(network)); + + update_needed = true; } +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#if defined TIZEN_EXT + else if (g_str_equal(property, "UpdateAssocReject")) { + connman_network_set_assoc_reject_table(connman_network, + g_supplicant_network_clone_assoc_reject_table(network)); + update_needed = true; + } +#endif + else + update_needed = false; + + if (update_needed) + connman_network_update(connman_network); #if defined TIZEN_EXT bssid = g_supplicant_network_get_bssid(network); maxrate = g_supplicant_network_get_maxrate(network); frequency = g_supplicant_network_get_frequency(network); wps = g_supplicant_network_get_wps(network); + phy_mode = g_supplicant_network_get_phy_mode(network); connman_network_set_bssid(connman_network, bssid); connman_network_set_maxrate(connman_network, maxrate); @@ -4423,6 +5710,11 @@ static void network_changed(GSupplicantNetwork *network, const char *property) connman_network_set_countrycode(connman_network, country_code); bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network); connman_network_set_bssid_list(connman_network, bssid_list); + connman_network_set_phy_mode(connman_network, phy_mode); + + if (g_str_equal(property, "CheckMultiBssidConnect") && + connman_network_get_associating(connman_network)) + network_connect(connman_network); #endif } @@ -4438,11 +5730,24 @@ static void network_associated(GSupplicantNetwork *network) interface = g_supplicant_network_get_interface(network); if (!interface) return; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + wifi = g_supplicant_interface_get_data(interface); if (!wifi) return; + /* P2P networks must not be treated as WiFi networks */ + if (wifi->p2p_connecting || wifi->p2p_device) + return; + identifier = g_supplicant_network_get_identifier(network); connman_network = connman_device_get_network(wifi->device, identifier); @@ -4452,7 +5757,22 @@ static void network_associated(GSupplicantNetwork *network) if (wifi->network) { if (wifi->network == connman_network) return; - +#if TIZEN_EXT + unsigned int ssid_len; + DBG("network1 ssid[%s] , OWE[%d],ssid[%s]", + (char *)connman_network_get_blob(wifi->network,"WiFi.SSID", &ssid_len), + connman_network_get_bool(wifi->network,"WiFi.TRANSITION_MODE"), + (char *)connman_network_get_blob(wifi->network,"WiFi.TRANSITION_MODE_SSID", &ssid_len)); + + DBG("network1 ssid[%s], OWE[%d], ssid[%s]", + (char *)connman_network_get_blob(connman_network,"WiFi.SSID",&ssid_len), + connman_network_get_bool(connman_network,"WiFi.TRANSITION_MODE"), + (char *)connman_network_get_blob(connman_network,"WiFi.TRANSITION_MODE_SSID", &ssid_len)); + if (connman_network_check_transition_mode(wifi->network, connman_network)) {//OWE trasition mode check + DBG("OWE transition mode is TRUE"); + return; + } +#endif /* * This should never happen, we got associated with * a network different than the one we were expecting. @@ -4477,6 +5797,50 @@ static void network_associated(GSupplicantNetwork *network) interface_state(interface); } +static void sta_authorized(GSupplicantInterface *interface, + const char *addr) +{ +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); + + DBG("wifi %p station %s authorized", wifi, addr); + + if (!wifi || !wifi->tethering) + return; + + __connman_tethering_client_register(addr); +} + +static void sta_deauthorized(GSupplicantInterface *interface, + const char *addr) +{ +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); + + DBG("wifi %p station %s deauthorized", wifi, addr); + + if (!wifi || !wifi->tethering) + return; + + __connman_tethering_client_unregister(addr); +} + static void apply_peer_services(GSupplicantPeer *peer, struct connman_peer *connman_peer) { @@ -4494,17 +5858,6 @@ static void apply_peer_services(GSupplicantPeer *peer, } } -static void add_station(const char *mac) -{ - connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI, - mac); -} - -static void remove_station(const char *mac) -{ - connman_technology_tethering_remove_station(mac); -} - static void peer_found(GSupplicantPeer *peer) { GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer); @@ -4512,6 +5865,7 @@ static void peer_found(GSupplicantPeer *peer) struct connman_peer *connman_peer; const char *identifier, *name; int ret; + #if defined TIZEN_EXT if (!wifi) return; @@ -4712,6 +6066,15 @@ static void network_merged(GSupplicantNetwork *network) if (!interface) return; +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + state = g_supplicant_interface_get_state(interface); if (state < G_SUPPLICANT_STATE_AUTHENTICATING) return; @@ -4769,17 +6132,60 @@ static void assoc_failed(void *user_data) struct connman_network *network = user_data; connman_network_set_associating(network, false); } + +static void scan_done(GSupplicantInterface *interface) +{ +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + + GList *list; + int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT; + struct wifi_data *wifi; + bool scanning; + + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (interface == wifi->interface) { + scanning = connman_device_get_scanning(wifi->device, + CONNMAN_SERVICE_TYPE_WIFI); + if (!scanning) + __connman_technology_notify_scan_done( + connman_device_get_string(wifi->device, "Interface"), scan_type); + break; + } + } +} #endif static void debug(const char *str) { +#if defined TIZEN_EXT + if (connman_setting_get_bool("ConnmanSupplicantDebug")) +#else if (getenv("CONNMAN_SUPPLICANT_DEBUG")) +#endif connman_debug("%s", str); } static void disconnect_reasoncode(GSupplicantInterface *interface, int reasoncode) { +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); if (wifi != NULL) { @@ -4789,6 +6195,15 @@ static void disconnect_reasoncode(GSupplicantInterface *interface, static void assoc_status_code(GSupplicantInterface *interface, int status_code) { +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET + /* + * Note: If supplicant interface's driver is wired then skip it, + * because it meanti only for ethernet not Wi-Fi. + */ + if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface))) + return; +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ + struct wifi_data *wifi = g_supplicant_interface_get_data(interface); if (wifi != NULL) { @@ -4796,7 +6211,11 @@ static void assoc_status_code(GSupplicantInterface *interface, int status_code) } } +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET +static GSupplicantCallbacks callbacks = { +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ static const GSupplicantCallbacks callbacks = { +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ .system_ready = system_ready, .system_killed = system_killed, .interface_added = interface_added, @@ -4810,16 +6229,17 @@ static const GSupplicantCallbacks callbacks = { .network_removed = network_removed, .network_changed = network_changed, .network_associated = network_associated, - .add_station = add_station, - .remove_station = remove_station, + .sta_authorized = sta_authorized, + .sta_deauthorized = sta_deauthorized, .peer_found = peer_found, .peer_lost = peer_lost, .peer_changed = peer_changed, .peer_request = peer_request, #if defined TIZEN_EXT .system_power_off = system_power_off, - .network_merged = network_merged, + .network_merged = network_merged, .assoc_failed = assoc_failed, + .scan_done = scan_done, #endif .debug = debug, .disconnect_reasoncode = disconnect_reasoncode, @@ -4846,8 +6266,7 @@ static void tech_remove(struct connman_technology *technology) wifi_technology = NULL; } -static GSupplicantSSID *ssid_ap_init(const char *ssid, - const char *passphrase) +static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) { GSupplicantSSID *ap; @@ -4945,29 +6364,32 @@ static void sta_remove_callback(int result, void *user_data) { struct wifi_tethering_info *info = user_data; - const char *driver = connman_option_get_string("wifi"); + const char *driver = connman_setting_get_string("wifi"); DBG("ifname %s result %d ", info->ifname, result); - if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { + if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { info->wifi->tethering = false; connman_technology_tethering_notify(info->technology, false); - g_free(info->ifname); - g_free(info->ssid); - g_free(info); - if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) { g_free(info->wifi->tethering_param->ssid); g_free(info->wifi->tethering_param); info->wifi->tethering_param = NULL; } + + g_free(info->ifname); + g_free(info->ssid); + g_free(info); return; } info->wifi->interface = NULL; g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge, +#ifdef TIZEN_EXT + 0, 0, 60, +#endif /* TIZEN_EXT */ ap_create_callback, info); } @@ -4995,10 +6417,9 @@ static int enable_wifi_tethering(struct connman_technology *technology, if (!interface) continue; - if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) - continue; - ifname = g_supplicant_interface_get_ifname(wifi->interface); + if (!ifname) + continue; if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) { DBG("%s does not support AP mode (detected)", ifname); @@ -5033,8 +6454,6 @@ static int enable_wifi_tethering(struct connman_technology *technology, goto failed; info->ifname = g_strdup(ifname); - if (!info->ifname) - goto failed; wifi->tethering_param->technology = technology; wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase); @@ -5137,6 +6556,33 @@ static int tech_set_regdom(struct connman_technology *technology, const char *al return g_supplicant_set_country(alpha2, regdom_callback, NULL); } +#if defined TIZEN_EXT && defined TIZEN_EXT_INS +static void supp_ins_init(void) +{ + const char *string; + GSupplicantINSPreferredFreq preferred_freq; + + string = connman_setting_get_string("INSPreferredFreqBSSID"); + if (g_strcmp0(string, "5GHz") == 0) + preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ; + else if (g_strcmp0(string, "2.4GHz") == 0) + preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ; + else + preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN; + + g_supplicant_set_ins_settings(preferred_freq, + connman_setting_get_bool("INSLastConnectedBSSID"), + connman_setting_get_bool("INSAssocReject"), + connman_setting_get_bool("INSSignalBSSID"), + connman_setting_get_uint("INSPreferredFreqBSSIDScore"), + connman_setting_get_uint("INSLastConnectedBSSIDScore"), + connman_setting_get_uint("INSAssocRejectScore"), + connman_setting_get_int("INSSignalLevel3_5GHz"), + connman_setting_get_int("INSSignalLevel3_24GHz") + ); +} +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ + static struct connman_technology_driver tech_driver = { .name = "wifi", .type = CONNMAN_SERVICE_TYPE_WIFI, @@ -5167,6 +6613,13 @@ static int wifi_init(void) return err; } +#if defined TIZEN_EXT + failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); +#endif + +#if defined TIZEN_EXT && defined TIZEN_EXT_INS + supp_ins_init(); +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ return 0; } @@ -5179,6 +6632,10 @@ static void wifi_exit(void) g_supplicant_unregister(&callbacks); connman_network_driver_unregister(&network_driver); + +#if defined TIZEN_EXT + g_hash_table_unref(failed_bssids); +#endif } CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,