diff options
author | Seonah Moon <seonah1.moon@samsung.com> | 2018-01-23 14:50:50 +0900 |
---|---|---|
committer | Seonah Moon <seonah1.moon@samsung.com> | 2018-01-23 14:50:55 +0900 |
commit | 30602f521a85820a9f6b7ac04876400e00c68b15 (patch) | |
tree | f035a4fcc014a034f3b492886d1e8395f327fd25 /gsupplicant | |
parent | a079cfe6f815f8c69055de834d1ccbdf1fd94ba7 (diff) | |
parent | 9362752a471a5c892d679548fbf2828d5fc5684b (diff) | |
download | connman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.gz connman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.bz2 connman-30602f521a85820a9f6b7ac04876400e00c68b15.zip |
Updated connman to version 1.35
Change-Id: I13526fbf80296a79be15548fc226a308941ac9ec
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'gsupplicant')
-rwxr-xr-x | gsupplicant/gsupplicant.h | 12 | ||||
-rw-r--r--[-rwxr-xr-x] | gsupplicant/supplicant.c | 718 |
2 files changed, 564 insertions, 166 deletions
diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index 123f3b2f..88606262 100755 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -157,7 +157,12 @@ struct _GSupplicantSSID { const char *eap; const char *passphrase; const char *identity; + const char *anonymous_identity; const char *ca_cert_path; + const char *subject_match; + const char *altsubject_match; + const char *domain_suffix_match; + const char *domain_match; const char *client_cert_path; const char *private_key_path; const char *private_key_passphrase; @@ -377,7 +382,8 @@ const char *g_supplicant_network_get_eap(GSupplicantNetwork *network); const char *g_supplicant_network_get_identity(GSupplicantNetwork *network); const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network); unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network); -void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network); +const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network, + unsigned int *wifi_vsie_len); #endif struct _GSupplicantCallbacks { @@ -389,6 +395,7 @@ struct _GSupplicantCallbacks { void (*p2p_support) (GSupplicantInterface *interface); void (*scan_started) (GSupplicantInterface *interface); void (*scan_finished) (GSupplicantInterface *interface); + void (*ap_create_fail) (GSupplicantInterface *interface); void (*network_added) (GSupplicantNetwork *network); void (*network_removed) (GSupplicantNetwork *network); #if defined TIZEN_EXT @@ -396,6 +403,7 @@ struct _GSupplicantCallbacks { #endif void (*network_changed) (GSupplicantNetwork *network, const char *property); + void (*network_associated) (GSupplicantNetwork *network); #if defined TIZEN_EXT void (*system_power_off) (void); void (*assoc_failed) (void *user_data); @@ -409,7 +417,7 @@ struct _GSupplicantCallbacks { void (*peer_request) (GSupplicantPeer *peer); void (*debug) (const char *str); void (*disconnect_reasoncode)(GSupplicantInterface *interface, - int reasoncode); + int reasoncode); void (*assoc_status_code)(GSupplicantInterface *interface, int reasoncode); }; diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 243dcd09..5e9f5095 100755..100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -143,6 +143,7 @@ static GHashTable *bss_mapping; static GHashTable *peer_mapping; static GHashTable *group_mapping; static GHashTable *pending_peer_connection; +static GHashTable *config_file_table; struct _GSupplicantWpsCredentials { unsigned char ssid[32]; @@ -150,6 +151,13 @@ struct _GSupplicantWpsCredentials { char *key; }; +struct added_network_information { + char * ssid; + GSupplicantSecurity security; + char * passphrase; + char * private_passphrase; +}; + struct _GSupplicantInterface { char *path; char *network_path; @@ -163,6 +171,7 @@ struct _GSupplicantInterface { unsigned int max_scan_ssids; bool p2p_support; bool p2p_finding; + bool ap_create_in_progress; dbus_bool_t ready; GSupplicantState state; dbus_bool_t scanning; @@ -177,10 +186,11 @@ struct _GSupplicantInterface { GHashTable *network_table; GHashTable *peer_table; GHashTable *group_table; - GHashTable *net_mapping; GHashTable *bss_mapping; void *data; const char *pending_peer_path; + GSupplicantNetwork *current_network; + struct added_network_information network_info; #if defined TIZEN_EXT int disconnect_reason; #endif @@ -211,7 +221,8 @@ struct g_supplicant_bss { #if defined TIZEN_EXT dbus_bool_t ft_psk; dbus_bool_t ft_ieee8021x; - GSList *vsie_list; + char *wifi_vsie; + unsigned int wifi_vsie_len; dbus_bool_t hs20; #endif unsigned int wps_capabilities; @@ -239,7 +250,8 @@ struct _GSupplicantNetwork { char *identity; char *phase2; unsigned int keymgmt; - GSList *vsie_list; + char *wifi_vsie; + unsigned int wifi_vsie_len; #endif }; @@ -266,12 +278,53 @@ struct _GSupplicantGroup { GSList *members; }; +struct interface_data { + GSupplicantInterface *interface; + char *path; /* Interface path cannot be taken from interface (above) as + * it might have been freed already. + */ + GSupplicantInterfaceCallback callback; + void *user_data; + bool network_remove_in_progress; + GSupplicantSSID *ssid; +}; + +struct interface_create_data { + char *ifname; + char *driver; + char *bridge; + GSupplicantInterface *interface; + GSupplicantInterfaceCallback callback; + void *user_data; +}; + +struct interface_connect_data { + GSupplicantInterface *interface; + char *path; + GSupplicantInterfaceCallback callback; + void *user_data; + union { + GSupplicantSSID *ssid; + GSupplicantPeerParams *peer; + }; +}; + +struct interface_scan_data { + GSupplicantInterface *interface; + char *path; + GSupplicantInterfaceCallback callback; + GSupplicantScanParams *scan_params; + void *user_data; +}; + +static int network_remove(struct interface_data *data); + static inline void debug(const char *format, ...) { char str[256]; va_list ap; - if (!callbacks_pointer->debug) + if (!callbacks_pointer || !callbacks_pointer->debug) return; va_start(ap, format); @@ -369,6 +422,70 @@ static GSupplicantState string2state(const char *state) return G_SUPPLICANT_STATE_UNKNOWN; } +static bool compare_network_parameters(GSupplicantInterface *interface, + GSupplicantSSID *ssid) +{ + if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len)) + return FALSE; + + if (interface->network_info.security != ssid->security) + return FALSE; + + if (interface->network_info.passphrase && + g_strcmp0(interface->network_info.passphrase, + ssid->passphrase) != 0) { + return FALSE; + } + + if (interface->network_info.private_passphrase && + g_strcmp0(interface->network_info.private_passphrase, + ssid->private_key_passphrase) != 0) { + return FALSE; + } + + return TRUE; +} + +static void remove_network_information(GSupplicantInterface * interface) +{ + g_free(interface->network_info.ssid); + g_free(interface->network_info.passphrase); + g_free(interface->network_info.private_passphrase); + interface->network_info.ssid = NULL; + interface->network_info.passphrase = NULL; + interface->network_info.private_passphrase = NULL; +} + +static int store_network_information(GSupplicantInterface * interface, + GSupplicantSSID *ssid) +{ + interface->network_info.ssid = g_malloc(ssid->ssid_len + 1); + if (interface->network_info.ssid != NULL) { + memcpy(interface->network_info.ssid, ssid->ssid, + ssid->ssid_len); + interface->network_info.ssid[ssid->ssid_len] = '\0'; + } else { + return -ENOMEM; + } + + interface->network_info.security = ssid->security; + + if ((ssid->security == G_SUPPLICANT_SECURITY_WEP || + ssid->security == G_SUPPLICANT_SECURITY_PSK || + ssid->security == G_SUPPLICANT_SECURITY_NONE) && + ssid->passphrase) { + interface->network_info.passphrase = g_strdup(ssid->passphrase); + } + + if (ssid->security == G_SUPPLICANT_SECURITY_IEEE8021X && + ssid->private_key_passphrase) { + interface->network_info.private_passphrase = + g_strdup(ssid->private_key_passphrase); + } + + return 0; +} + static void callback_system_ready(void) { if (system_ready) @@ -457,6 +574,17 @@ static void callback_scan_started(GSupplicantInterface *interface) callbacks_pointer->scan_started(interface); } +static void callback_ap_create_fail(GSupplicantInterface *interface) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->ap_create_fail) + return; + + callbacks_pointer->ap_create_fail(interface); +} + static void callback_scan_finished(GSupplicantInterface *interface) { if (!callbacks_pointer) @@ -526,6 +654,17 @@ static void callback_network_changed(GSupplicantNetwork *network, callbacks_pointer->network_changed(network, property); } +static void callback_network_associated(GSupplicantNetwork *network) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->network_associated) + return; + + callbacks_pointer->network_associated(network); +} + static void callback_peer_found(GSupplicantPeer *peer) { if (!callbacks_pointer) @@ -616,7 +755,6 @@ static void remove_interface(gpointer data) GSupplicantInterface *interface = data; g_hash_table_destroy(interface->bss_mapping); - g_hash_table_destroy(interface->net_mapping); g_hash_table_destroy(interface->network_table); g_hash_table_destroy(interface->peer_table); g_hash_table_destroy(interface->group_table); @@ -647,6 +785,7 @@ static void remove_interface(gpointer data) g_free(interface->ifname); g_free(interface->driver); g_free(interface->bridge); + remove_network_information(interface); g_free(interface); } @@ -669,7 +808,7 @@ static void remove_network(gpointer data) g_free(network->phase2); #endif #if defined TIZEN_EXT - g_slist_free_full(network->vsie_list, g_free); + g_free(network->wifi_vsie); #endif g_free(network); @@ -681,7 +820,7 @@ static void remove_bss(gpointer data) g_free(bss->path); #if defined TIZEN_EXT - g_slist_free_full(bss->vsie_list, g_free); + g_free(bss->wifi_vsie); #endif g_free(bss); } @@ -704,6 +843,7 @@ static void remove_peer(gpointer data) g_free(peer->path); g_free(peer->name); g_free(peer->identifier); + g_free(peer->widi_ies); g_free(peer); } @@ -881,20 +1021,59 @@ static void interface_capability(const char *key, DBusMessageIter *iter, key, dbus_message_iter_get_arg_type(iter)); } +struct set_apscan_data +{ + unsigned int ap_scan; + GSupplicantInterface *interface; +}; + static void set_apscan(DBusMessageIter *iter, void *user_data) { - unsigned int ap_scan = *(unsigned int *)user_data; + struct set_apscan_data *data = user_data; + unsigned int ap_scan = data->ap_scan; dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ap_scan); } +static void set_apscan_complete(const char *error, + DBusMessageIter *iter, void *user_data) +{ + struct set_apscan_data *data = user_data; + GSupplicantInterface *interface = data->interface; + + if (error) { + interface->ap_create_in_progress = false; + SUPPLICANT_DBG("Set AP scan error %s", error); + goto error; + } + + interface->ap_create_in_progress = true; +error: + dbus_free(data); +} + int g_supplicant_interface_set_apscan(GSupplicantInterface *interface, unsigned int ap_scan) { - return supplicant_dbus_property_set(interface->path, + struct set_apscan_data *data; + int ret; + + data = dbus_malloc0(sizeof(*data)); + + if (!data) + return -ENOMEM; + + data->ap_scan = ap_scan; + data->interface = interface; + + ret = supplicant_dbus_property_set(interface->path, SUPPLICANT_INTERFACE ".Interface", - "ApScan", DBUS_TYPE_UINT32_AS_STRING, - set_apscan, NULL, &ap_scan, NULL); + "ApScan", DBUS_TYPE_UINT32_AS_STRING, + set_apscan, set_apscan_complete, data, NULL); + if (ret < 0) + dbus_free(data); + + return ret; } void g_supplicant_interface_set_data(GSupplicantInterface *interface, @@ -1379,29 +1558,16 @@ bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network) return false; } -void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network) +const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network, + unsigned int *wifi_vsie_len) { - GSList *vsie_list = NULL; - - if (!network) + if (!network) { + *wifi_vsie_len = 0; return NULL; - - if (g_slist_length(network->vsie_list) > 0) { - GSList *list = NULL; - unsigned char *vsie = NULL; - for (list = network->vsie_list; list; list = list->next) { - unsigned char *ie = (unsigned char *)list->data; - vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1) - - if (vsie) { - memcpy(vsie, ie, ie[1]+2); - vsie_list = g_slist_append(vsie_list, vsie); - } else - SUPPLICANT_DBG("Failed to allocate memory"); - } } - return vsie_list; + *wifi_vsie_len = network->wifi_vsie_len; + return network->wifi_vsie; } #endif @@ -1544,10 +1710,6 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data) if (g_strcmp0(path, "/") == 0) return; - network = g_hash_table_lookup(interface->net_mapping, path); - if (network) - return; - network = g_try_new0(GSupplicantNetwork, 1); if (!network) return; @@ -1573,19 +1735,8 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data) static void interface_network_removed(DBusMessageIter *iter, void *user_data) { - GSupplicantInterface *interface = user_data; - GSupplicantNetwork *network; - const char *path = NULL; - - dbus_message_iter_get_basic(iter, &path); - if (!path) - return; - - network = g_hash_table_lookup(interface->net_mapping, path); - if (!network) - return; - - g_hash_table_remove(interface->net_mapping, path); + SUPPLICANT_DBG(""); + return; } static char *create_name(unsigned char *ssid, int ssid_len) @@ -1656,7 +1807,7 @@ static char *create_group(struct g_supplicant_bss *bss) return g_string_free(str, FALSE); } -static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss) +static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) { GSupplicantInterface *interface = bss->interface; GSupplicantNetwork *network; @@ -1666,7 +1817,7 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss) SUPPLICANT_DBG("New group created: %s", group); if (!group) - return; + return -ENOMEM; network = g_hash_table_lookup(interface->network_table, group); if (network) { @@ -1679,7 +1830,7 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network = g_try_new0(GSupplicantNetwork, 1); if (!network) { g_free(group); - return; + return -ENOMEM; } network->interface = interface; @@ -1698,18 +1849,14 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss) #if defined TIZEN_EXT network->keymgmt = bss->keymgmt; - if (g_slist_length(bss->vsie_list) > 0) { - GSList *list = NULL; - unsigned char *vsie = NULL; - for (list = bss->vsie_list; list; list = list->next) { - unsigned char *ie = (unsigned char *)list->data; - vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1) - - if (vsie) { - memcpy(vsie, ie, ie[1]+2); - network->vsie_list = g_slist_append(network->vsie_list, vsie); - } else - SUPPLICANT_DBG("Failed to allocate memory."); + if (bss->wifi_vsie_len > 0) { + SUPPLICANT_DBG("vsie len: %d", bss->wifi_vsie_len); + network->wifi_vsie = (char *)g_try_malloc0(bss->wifi_vsie_len); + if(network->wifi_vsie) { + network->wifi_vsie_len = bss->wifi_vsie_len; + memcpy(network->wifi_vsie, bss->wifi_vsie, network->wifi_vsie_len); + } else { + SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie"); } } @@ -1736,7 +1883,12 @@ done: network->wps_capabilities |= bss->wps_capabilities; } - if (bss->signal > network->signal) { + /* + * 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 (network != interface->current_network && + bss->signal > network->signal) { network->signal = bss->signal; network->best_bss = bss; callback_network_changed(network, "Signal"); @@ -1746,6 +1898,8 @@ done: g_hash_table_replace(network->bss_table, bss->path, bss); g_hash_table_replace(bss_mapping, bss->path, interface); + + return 0; } static void bss_rates(DBusMessageIter *iter, void *user_data) @@ -1893,6 +2047,9 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) { struct g_supplicant_bss *bss = user_data; const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 }; +#if defined TIZEN_EXT + const unsigned char WIFI_OUI[] = {0x00, 0x16, 0x32}; +#endif unsigned char *ie, *ie_end; DBusMessageIter array; unsigned int value; @@ -1924,20 +2081,16 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end; ie += ie[1] + 2) { #if defined TIZEN_EXT - unsigned char *vsie; - int vsie_len = 0; - if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) { - SUPPLICANT_DBG("IE: match vendor specific data"); - - vsie_len = ie[1]+2; // tag number size(1), tag length size(1) - vsie = (unsigned char *)g_try_malloc0(vsie_len); - - if (vsie) { - memcpy(vsie, ie, vsie_len); - bss->vsie_list = g_slist_append(bss->vsie_list, vsie); - } else - SUPPLICANT_DBG("Failed to allocate memory"); - continue; + if((ie[0] == VENDOR_SPECIFIC_INFO) && (memcmp(ie+2, WIFI_OUI, sizeof(WIFI_OUI)) == 0)) { + SUPPLICANT_DBG("IE: match WIFI_OUI"); + bss->wifi_vsie = (char *)g_try_malloc0(ie[1] + 2); // tag number size(1), tag length size(1) + if (bss->wifi_vsie) { + bss->wifi_vsie_len = ie[1] + 2; + memcpy(bss->wifi_vsie, ie, bss->wifi_vsie_len); + } else { + SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie"); + } + continue; } #endif if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN || @@ -2200,7 +2353,8 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter, supplicant_dbus_property_foreach(iter, bss_property, bss); bss_compute_security(bss); - add_or_replace_bss_to_network(bss); + if (add_or_replace_bss_to_network(bss) < 0) + SUPPLICANT_DBG("add_or_replace_bss_to_network failed"); } static void interface_bss_added_without_keys(DBusMessageIter *iter, @@ -2219,7 +2373,8 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter, bss_property, bss, NULL); bss_compute_security(bss); - add_or_replace_bss_to_network(bss); + if (add_or_replace_bss_to_network(bss) < 0) + SUPPLICANT_DBG("add_or_replace_bss_to_network failed"); } static void update_signal(gpointer key, gpointer value, @@ -2245,6 +2400,75 @@ static void update_network_signal(GSupplicantNetwork *network) SUPPLICANT_DBG("New network signal %d", network->signal); } +static void interface_current_bss(GSupplicantInterface *interface, + DBusMessageIter *iter) +{ + GSupplicantNetwork *network; + struct g_supplicant_bss *bss; + const char *path; + + dbus_message_iter_get_basic(iter, &path); + if (g_strcmp0(path, "/") == 0) { + interface->current_network = NULL; + return; + } + + interface_bss_added_without_keys(iter, interface); + + network = g_hash_table_lookup(interface->bss_mapping, path); + if (!network) + return; + + bss = g_hash_table_lookup(network->bss_table, path); + if (!bss) + return; + + interface->current_network = network; + + if (bss != network->best_bss) { + /* + * This is the case where either wpa_s got associated + * to a BSS different than the one ConnMan considers + * the best, or we are roaming. + */ + SUPPLICANT_DBG("Update best BSS for %s", network->name); + + network->best_bss = bss; + + if (network->signal != bss->signal) { + SUPPLICANT_DBG("New network signal %d dBm", + bss->signal); + + network->signal = bss->signal; + callback_network_changed(network, "Signal"); + } + } + + /* + * wpa_s could notify about CurrentBSS in any state once + * it got associated. It is not sure such notification will + * arrive together with transition to ASSOCIATED state. + * In fact, for networks with security WEP or OPEN, it + * always arrives together with transition to COMPLETED. + */ + switch (interface->state) { + case G_SUPPLICANT_STATE_UNKNOWN: + case G_SUPPLICANT_STATE_DISABLED: + case G_SUPPLICANT_STATE_DISCONNECTED: + case G_SUPPLICANT_STATE_INACTIVE: + case G_SUPPLICANT_STATE_SCANNING: + case G_SUPPLICANT_STATE_AUTHENTICATING: + case G_SUPPLICANT_STATE_ASSOCIATING: + return; + case G_SUPPLICANT_STATE_ASSOCIATED: + case G_SUPPLICANT_STATE_4WAY_HANDSHAKE: + case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: + case G_SUPPLICANT_STATE_COMPLETED: + callback_network_associated(network); + break; + } +} + static void interface_bss_removed(DBusMessageIter *iter, void *user_data) { GSupplicantInterface *interface = user_data; @@ -2279,10 +2503,37 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data) static void set_config_methods(DBusMessageIter *iter, void *user_data) { - const char *config_methods = "push_button"; + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data); +} + +static void wps_property(const char *key, DBusMessageIter *iter, + void *user_data) +{ + GSupplicantInterface *interface = user_data; + + if (!interface) + return; + + SUPPLICANT_DBG("key: %s", key); + + if (g_strcmp0(key, "ConfigMethods") == 0) { + const char *config_methods = "push_button", *str = NULL; + + dbus_message_iter_get_basic(iter, &str); + if (str && strlen(str) > 0) { + /* It was already set at wpa_s level, don't modify it. */ + SUPPLICANT_DBG("%s", str); + return; + } + + supplicant_dbus_property_set(interface->path, + SUPPLICANT_INTERFACE ".Interface.WPS", + "ConfigMethods", DBUS_TYPE_STRING_AS_STRING, + set_config_methods, NULL, &config_methods, NULL); + + SUPPLICANT_DBG("No value. Set %s", config_methods); + } - dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, - &config_methods); } static void interface_property(const char *key, DBusMessageIter *iter, @@ -2311,11 +2562,9 @@ static void interface_property(const char *key, DBusMessageIter *iter, debug_strvalmap("Mode capability", mode_capa_map, interface->mode_capa); - - supplicant_dbus_property_set(interface->path, + supplicant_dbus_property_get_all(interface->path, SUPPLICANT_INTERFACE ".Interface.WPS", - "ConfigMethods", DBUS_TYPE_STRING_AS_STRING, - set_config_methods, NULL, NULL, NULL); + wps_property, interface, interface); if (interface->ready) callback_interface_added(interface); @@ -2339,6 +2588,14 @@ static void interface_property(const char *key, DBusMessageIter *iter, interface->state = string2state(str); callback_interface_state(interface); } + + if (interface->ap_create_in_progress) { + if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) + callback_ap_create_fail(interface); + + interface->ap_create_in_progress = false; + } + if (interface->state == G_SUPPLICANT_STATE_DISABLED) interface->ready = FALSE; else @@ -2386,8 +2643,17 @@ static void interface_property(const char *key, DBusMessageIter *iter, g_free(interface->bridge); interface->bridge = g_strdup(str); } + } else if (g_strcmp0(key, "ConfigFile") == 0) { + const char *str = NULL; + + dbus_message_iter_get_basic(iter, &str); + if (str && strlen(str) > 0 && interface->ifname) { + SUPPLICANT_DBG("New {%s, %s}", interface->ifname, str); + g_hash_table_replace(config_file_table, + g_strdup(interface->ifname), g_strdup(str)); + } } else if (g_strcmp0(key, "CurrentBSS") == 0) { - interface_bss_added_without_keys(iter, interface); + interface_current_bss(interface, iter); } else if (g_strcmp0(key, "CurrentNetwork") == 0) { #if defined TIZEN_EXT if (interface->state != G_SUPPLICANT_STATE_COMPLETED) @@ -2414,9 +2680,10 @@ static void interface_property(const char *key, DBusMessageIter *iter, dbus_message_iter_get_basic(iter, &status_code); callback_assoc_status_code(interface, status_code); } - } else + } else { SUPPLICANT_DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter)); + } } static void scan_network_update(DBusMessageIter *iter, void *user_data) @@ -2489,8 +2756,6 @@ static GSupplicantInterface *interface_alloc(const char *path) g_str_equal, NULL, remove_peer); interface->group_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_group); - interface->net_mapping = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, NULL); interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); @@ -2503,6 +2768,7 @@ static void interface_added(DBusMessageIter *iter, void *user_data) { GSupplicantInterface *interface; const char *path = NULL; + bool properties_appended = GPOINTER_TO_UINT(user_data); SUPPLICANT_DBG(""); @@ -2521,18 +2787,20 @@ static void interface_added(DBusMessageIter *iter, void *user_data) if (!interface) return; + if (!properties_appended) { + supplicant_dbus_property_get_all(path, + SUPPLICANT_INTERFACE ".Interface", + interface_property, interface, + interface); + return; + } + dbus_message_iter_next(iter); if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { supplicant_dbus_property_foreach(iter, interface_property, interface); interface_property(NULL, NULL, interface); - return; } - - supplicant_dbus_property_get_all(path, - SUPPLICANT_INTERFACE ".Interface", - interface_property, interface, - interface); } static void interface_removed(DBusMessageIter *iter, void *user_data) @@ -2635,6 +2903,7 @@ static void signal_name_owner_changed(const char *path, DBusMessageIter *iter) g_hash_table_remove_all(bss_mapping); g_hash_table_remove_all(peer_mapping); g_hash_table_remove_all(group_mapping); + g_hash_table_remove_all(config_file_table); g_hash_table_remove_all(interface_table); callback_system_killed(); } @@ -2662,7 +2931,7 @@ static void signal_interface_added(const char *path, DBusMessageIter *iter) SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH); if (g_strcmp0(path, SUPPLICANT_PATH) == 0) - interface_added(iter, NULL); + interface_added(iter, GUINT_TO_POINTER(true)); } static void signal_interface_removed(const char *path, DBusMessageIter *iter) @@ -2828,7 +3097,14 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) g_hash_table_remove(interface->network_table, network->group); - add_or_replace_bss_to_network(new_bss); + if (add_or_replace_bss_to_network(new_bss) < 0) { + /* Remove entries in hash tables to handle the + * failure in add_or_replace_bss_to_network + */ + g_hash_table_remove(bss_mapping, path); + g_hash_table_remove(interface->bss_mapping, path); + g_hash_table_remove(network->bss_table, path); + } return; } @@ -2841,6 +3117,10 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) network->wps = FALSE; #endif + /* Consider only property changes of the connected BSS */ + if (network == interface->current_network && bss != network->best_bss) + return; + if (bss->signal == network->signal) #ifndef TIZEN_EXT return; @@ -3097,7 +3377,7 @@ static void peer_groups_relation(DBusMessageIter *iter, void *user_data) if (!group) return; - elem = g_slist_find_custom(data->old_groups, str, g_str_equal); + elem = g_slist_find_custom(data->old_groups, str, (GCompareFunc)g_strcmp0); if (elem) { data->old_groups = g_slist_remove_link(data->old_groups, elem); peer->groups = g_slist_concat(elem, peer->groups); @@ -3717,6 +3997,7 @@ int g_supplicant_set_country(const char *alpha2, const void *user_data) { struct supplicant_regdom *regdom; + int ret; SUPPLICANT_DBG("Country setting %s", alpha2); @@ -3731,10 +4012,15 @@ int g_supplicant_set_country(const char *alpha2, regdom->alpha2 = alpha2; regdom->user_data = user_data; - return supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE, + ret = supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE, "Country", DBUS_TYPE_STRING_AS_STRING, country_params, country_result, regdom, NULL); + if (ret < 0) { + dbus_free(regdom); + SUPPLICANT_DBG("Unable to set Country configuration"); + } + return ret; } int g_supplicant_interface_set_country(GSupplicantInterface *interface, @@ -3743,6 +4029,7 @@ int g_supplicant_interface_set_country(GSupplicantInterface *interface, void *user_data) { struct supplicant_regdom *regdom; + int ret; regdom = dbus_malloc0(sizeof(*regdom)); if (!regdom) @@ -3752,11 +4039,17 @@ int g_supplicant_interface_set_country(GSupplicantInterface *interface, regdom->alpha2 = alpha2; regdom->user_data = user_data; - return supplicant_dbus_property_set(interface->path, + ret = supplicant_dbus_property_set(interface->path, SUPPLICANT_INTERFACE ".Interface", "Country", DBUS_TYPE_STRING_AS_STRING, country_params, country_result, regdom, NULL); + if (ret < 0) { + dbus_free(regdom); + SUPPLICANT_DBG("Unable to set Country configuration"); + } + + return ret; } bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface) @@ -3896,43 +4189,6 @@ GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interf return peer; } -struct interface_data { - GSupplicantInterface *interface; - char *path; /* Interface path cannot be taken from interface (above) as - * it might have been freed already. - */ - GSupplicantInterfaceCallback callback; - void *user_data; -}; - -struct interface_create_data { - char *ifname; - char *driver; - char *bridge; - GSupplicantInterface *interface; - GSupplicantInterfaceCallback callback; - void *user_data; -}; - -struct interface_connect_data { - GSupplicantInterface *interface; - char *path; - GSupplicantInterfaceCallback callback; - union { - GSupplicantSSID *ssid; - GSupplicantPeerParams *peer; - }; - void *user_data; -}; - -struct interface_scan_data { - GSupplicantInterface *interface; - char *path; - GSupplicantInterfaceCallback callback; - GSupplicantScanParams *scan_params; - void *user_data; -}; - static void interface_create_data_free(struct interface_create_data *data) { g_free(data->ifname); @@ -4026,6 +4282,7 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data) { struct interface_create_data *data = user_data; DBusMessageIter dict; + char *config_file = NULL; SUPPLICANT_DBG(""); @@ -4042,6 +4299,14 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data) supplicant_dbus_dict_append_basic(&dict, "BridgeIfname", DBUS_TYPE_STRING, &data->bridge); + config_file = g_hash_table_lookup(config_file_table, data->ifname); + if (config_file) { + SUPPLICANT_DBG("[%s] ConfigFile %s", data->ifname, config_file); + + supplicant_dbus_dict_append_basic(&dict, "ConfigFile", + DBUS_TYPE_STRING, &config_file); + } + supplicant_dbus_dict_close(iter, &dict); } @@ -4162,6 +4427,7 @@ static void interface_remove_result(const char *error, if (error) { err = -EIO; + SUPPLICANT_DBG("error: %s", error); goto done; } @@ -4470,7 +4736,7 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface, static int parse_supplicant_error(DBusMessageIter *iter) { - int err = -ECANCELED; + int err = -ECONNABORTED; char *key; if (!iter) @@ -4554,9 +4820,10 @@ static void interface_add_network_result(const char *error, SUPPLICANT_DBG("PATH: %s", path); - g_free(interface->network_path); interface->network_path = g_strdup(path); + store_network_information(interface, data->ssid); + #if defined TIZEN_EXT SUPPLICANT_DBG(".Interface.SelectNetworkFreq"); #endif @@ -4888,6 +5155,30 @@ static void add_network_security_eap(DBusMessageIter *dict, DBUS_TYPE_STRING, &ssid->identity); #endif + if(ssid->anonymous_identity) + supplicant_dbus_dict_append_basic(dict, "anonymous_identity", + DBUS_TYPE_STRING, + &ssid->anonymous_identity); + + if(ssid->subject_match) + supplicant_dbus_dict_append_basic(dict, "subject_match", + DBUS_TYPE_STRING, + &ssid->subject_match); + + if(ssid->altsubject_match) + supplicant_dbus_dict_append_basic(dict, "altsubject_match", + DBUS_TYPE_STRING, + &ssid->altsubject_match); + + if(ssid->domain_suffix_match) + supplicant_dbus_dict_append_basic(dict, "domain_suffix_match", + DBUS_TYPE_STRING, + &ssid->domain_suffix_match); + + if(ssid->domain_match) + supplicant_dbus_dict_append_basic(dict, "domain_match", + DBUS_TYPE_STRING, + &ssid->domain_match); g_free(eap_value); } @@ -5200,6 +5491,7 @@ static void wps_process_credentials(DBusMessageIter *iter, void *user_data) dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials); } + #if defined TIZEN_EXT #define NETCONFIG_SERVICE "net.netconfig" #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" @@ -5248,13 +5540,11 @@ static void decryption_request_reply(DBusPendingCall *call, if (dbus_set_error_from_message(&error, reply)) { SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message); dbus_error_free(&error); - ret = -EINVAL; goto done; } if (dbus_message_iter_init(reply, &args) == FALSE) { SUPPLICANT_DBG("dbus_message_iter_init() failed"); - ret = -EINVAL; goto done; } @@ -5269,7 +5559,6 @@ static void decryption_request_reply(DBusPendingCall *call, interface_add_network_result, data, data->interface); -done: if (ret < 0) { SUPPLICANT_DBG("AddNetwork failed %d", ret); callback_assoc_failed(decrypt_request_data.data->user_data); @@ -5278,6 +5567,7 @@ done: dbus_free(data); } +done: dbus_message_unref(reply); dbus_pending_call_unref(call); @@ -5338,7 +5628,10 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, void *user_data) { struct interface_connect_data *data; - int ret; + struct interface_data *intf_data; + int ret = 0; + + SUPPLICANT_DBG(""); if (!interface) return -EINVAL; @@ -5367,19 +5660,64 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, SUPPLICANT_INTERFACE ".Interface.WPS", "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING, wps_process_credentials, wps_start, data, interface); - } else -#if defined TIZEN_EXT - if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) { - ret = send_decryption_request(ssid->passphrase, data); - if (ret < 0) - SUPPLICANT_DBG("Decryption request failed %d", ret); + } else { + /* By the time there is a request for connect and the network + * path is not NULL it means that connman has not removed the + * previous network pointer. This can happen in the case AP + * deauthenticated client and connman does not remove the + * previously connected network pointer. This causes supplicant + * to reallocate the memory for struct wpa_ssid again even if it + * is the same SSID. This causes memory usage of wpa_supplicnat + * to go high. The idea here is that if the previously connected + * network is not removed at the time of next connection attempt + * check if the network path is not NULL. In case it is non-NULL + * first remove the network and then once removal is successful, add + * the network. + */ + + if (interface->network_path != NULL) { + g_free(data->path); + dbus_free(data); + + /* + * If this add network is for the same network for + * which wpa_supplicant already has a profile then do + * not need to add another profile. Only if the + * profile that needs to get added is different from + * what is there in wpa_s delete the current one. A + * network is identified by its SSID, security_type + * and passphrase (private passphrase in case security + * type is 802.11x). + */ + if (compare_network_parameters(interface, ssid)) { + return -EALREADY; + } + + intf_data = dbus_malloc0(sizeof(*intf_data)); + if (!intf_data) + return -ENOMEM; + + intf_data->interface = interface; + intf_data->path = g_strdup(interface->path); + intf_data->callback = callback; + intf_data->ssid = ssid; + intf_data->user_data = user_data; + intf_data->network_remove_in_progress = TRUE; + network_remove(intf_data); } else +#if defined TIZEN_EXT + if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) { + ret = send_decryption_request(ssid->passphrase, data); + if (ret < 0) + SUPPLICANT_DBG("Decryption request failed %d", ret); + } else #endif - ret = supplicant_dbus_method_call(interface->path, - SUPPLICANT_INTERFACE ".Interface", "AddNetwork", - interface_add_network_params, - interface_add_network_result, data, - interface); + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, data, + interface); + } if (ret < 0) { g_free(data->path); @@ -5394,22 +5732,47 @@ static void network_remove_result(const char *error, DBusMessageIter *iter, void *user_data) { struct interface_data *data = user_data; + struct interface_connect_data *connect_data; int result = 0; SUPPLICANT_DBG(""); if (error) { result = -EIO; + SUPPLICANT_DBG("error: %s", error); + if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod", error) == 0) result = -ECONNABORTED; } - g_free(data->path); + g_free(data->interface->network_path); + data->interface->network_path = NULL; - if (data->callback) - data->callback(result, data->interface, data->user_data); + remove_network_information(data->interface); + + if (data->network_remove_in_progress == TRUE) { + data->network_remove_in_progress = FALSE; + connect_data = dbus_malloc0(sizeof(*connect_data)); + if (!connect_data) + return; + + connect_data->interface = data->interface; + connect_data->path = g_strdup(data->path); + connect_data->callback = data->callback; + connect_data->ssid = data->ssid; + connect_data->user_data = data->user_data; + supplicant_dbus_method_call(data->interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, connect_data, + connect_data->interface); + } else { + if (data->callback) + data->callback(result, data->interface, data->user_data); + } + g_free(data->path); dbus_free(data); } @@ -5455,25 +5818,31 @@ static void interface_disconnect_result(const char *error, if (error) { result = -EIO; + SUPPLICANT_DBG("error: %s", error); + if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod", error) == 0) result = -ECONNABORTED; } - if (result < 0 && data->callback) { - data->callback(result, data->interface, data->user_data); - data->callback = NULL; - } - /* If we are disconnecting from previous WPS successful * association. i.e.: it did not went through AddNetwork, * and interface->network_path was never set. */ if (!data->interface->network_path) { + if (data->callback) + data->callback(result, data->interface, + data->user_data); + g_free(data->path); dbus_free(data); return; } + if (result < 0 && data->callback) { + data->callback(result, data->interface, data->user_data); + data->callback = NULL; + } + if (result != -ECONNABORTED) { if (network_remove(data) < 0) { g_free(data->path); @@ -5630,8 +5999,10 @@ static void interface_p2p_connect_result(const char *error, SUPPLICANT_DBG(""); - if (error) + if (error) { + SUPPLICANT_DBG("error: %s", error); err = parse_supplicant_error(iter); + } if (data->callback) data->callback(err, data->interface, data->user_data); @@ -5689,6 +6060,9 @@ int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface, return -ENOTSUP; data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + data->interface = interface; data->path = g_strdup(interface->path); data->peer = peer_params; @@ -5833,6 +6207,9 @@ int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface, return -ENOTSUP; data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + data->registration = true; data->interface = interface; data->service = p2p_service_params; @@ -5863,6 +6240,9 @@ int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface, return -ENOTSUP; data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + data->interface = interface; data->service = p2p_service_params; @@ -5948,6 +6328,9 @@ int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params, return -EFAULT; data = dbus_malloc0(sizeof(*data)); + if (!data) + return -ENOMEM; + data->service = p2p_service_params; data->callback = callback; data->user_data = user_data; @@ -6062,6 +6445,8 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) NULL, NULL); pending_peer_connection = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + config_file_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); supplicant_dbus_setup(connection); @@ -6139,6 +6524,11 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks) g_supplicant_filter, NULL); } + if (config_file_table) { + g_hash_table_destroy(config_file_table); + config_file_table = NULL; + } + if (bss_mapping) { g_hash_table_destroy(bss_mapping); bss_mapping = NULL; |