Imported Upstream connman version 1.38
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index d59085d..02e6a62 100755 (executable)
 #include "dbus.h"
 #include "gsupplicant.h"
 
+#if defined TIZEN_EXT
+#include "setting.h"
+#endif
+
 #define IEEE80211_CAP_ESS      0x0001
 #define IEEE80211_CAP_IBSS     0x0002
 #define IEEE80211_CAP_PRIVACY  0x0010
 
 static DBusConnection *connection;
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static GSupplicantCallbacks *callbacks_pointer;
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 static const GSupplicantCallbacks *callbacks_pointer;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 
 static dbus_bool_t system_available = FALSE;
 static dbus_bool_t system_ready = FALSE;
@@ -302,6 +310,10 @@ struct g_supplicant_bss {
        dbus_bool_t sae;
        dbus_bool_t owe;
        dbus_bool_t dpp;
+       dbus_bool_t owe_transition_mode;
+       unsigned int transition_mode_ssid_len;
+       unsigned char transition_mode_bssid[6];
+       unsigned char transition_mode_ssid[32];
 #endif
 };
 
@@ -330,8 +342,10 @@ struct _GSupplicantNetwork {
        GSList *vsie_list;
        unsigned char country_code[COUNTRY_CODE_LENGTH];
        GSupplicantPhy_mode phy_mode;
-#endif
-#if defined TIZEN_EXT
+       dbus_bool_t owe_transition_mode;
+       unsigned int transition_mode_ssid_len;
+       unsigned char transition_mode_bssid[6];
+       unsigned char transition_mode_ssid[32];
        unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
        GHashTable *assoc_reject_table;
 #endif
@@ -446,6 +460,7 @@ struct assoc_count_data {
 };
 
 static unsigned int last_connected_bss_timeout = 0;
+static bool simplified_log = true;
 #endif
 
 static int network_remove(struct interface_data *data);
@@ -906,6 +921,19 @@ static void callback_sta_deauthorized(GSupplicantInterface *interface,
        callbacks_pointer->sta_deauthorized(interface, addr);
 }
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static void callback_eap(GSupplicantInterface *interface, bool status)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->eap)
+               return;
+
+       callbacks_pointer->eap(interface, status);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
 static void callback_peer_found(GSupplicantPeer *peer)
 {
        if (!callbacks_pointer)
@@ -1110,7 +1138,9 @@ static void debug_strvalmap(const char *label, struct strvalmap *map,
                                                        unsigned int val)
 {
        int i;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        for (i = 0; map[i].str; i++) {
                if (val & map[i].val)
                        SUPPLICANT_DBG("%s: %s", label, map[i].str);
@@ -1285,6 +1315,24 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                                key, dbus_message_iter_get_arg_type(iter));
 }
 
+static void set_bss_expiration_age(DBusMessageIter *iter, void *user_data)
+{
+       unsigned int bss_expiration_age = GPOINTER_TO_UINT(user_data);
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+                               &bss_expiration_age);
+}
+
+int g_supplicant_interface_set_bss_expiration_age(GSupplicantInterface *interface,
+                                       unsigned int bss_expiration_age)
+{
+       return supplicant_dbus_property_set(interface->path,
+                                      SUPPLICANT_INTERFACE ".Interface",
+                                      "BSSExpireAge", DBUS_TYPE_UINT32_AS_STRING,
+                                      set_bss_expiration_age, NULL,
+                                      GUINT_TO_POINTER(bss_expiration_age), NULL);
+}
+
 struct set_apscan_data
 {
        unsigned int ap_scan;
@@ -1798,6 +1846,34 @@ const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
 
        return (const unsigned char *)network->best_bss->bssid;
 }
+dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return FALSE;
+
+       return network->owe_transition_mode;
+}
+
+
+const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return NULL;
+
+       return (const unsigned char *)network->transition_mode_bssid;
+}
+
+const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network,
+                                               unsigned int *transition_mode_ssid_len)
+{
+       if (!network) {
+               *transition_mode_ssid_len = 0;
+               return NULL;
+       }
+
+       *transition_mode_ssid_len = network->transition_mode_ssid_len;
+       return network->transition_mode_ssid;
+}
 
 unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
 {
@@ -2437,6 +2513,14 @@ static char *create_group(struct g_supplicant_bss *bss)
 
        return g_string_free(str, FALSE);
 }
+#if defined TIZEN_EXT
+static void update_network_with_best_bss(GSupplicantNetwork *network,
+               struct g_supplicant_bss *best_bss)
+{
+       network->signal = best_bss->signal;
+       network->frequency = best_bss->frequency;
+       network->best_bss = best_bss;
+}
 
 static bool update_best_bss(GSupplicantNetwork *network,
                struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss)
@@ -2444,10 +2528,16 @@ static bool update_best_bss(GSupplicantNetwork *network,
        int score_new;
        int score_best;
 
+       if (network->best_bss == NULL) {
+               update_network_with_best_bss(network, bss);
+               return true;
+       }
+
        score_new = calculate_score(
                compare_bssid(bss->bssid, network->last_connected_bssid),
                get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
                bss->frequency, bss->signal);
+
        score_best = calculate_score(
                compare_bssid(network->best_bss->bssid, network->last_connected_bssid),
                get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
@@ -2458,9 +2548,7 @@ static bool update_best_bss(GSupplicantNetwork *network,
                        MAC2STR(bss->bssid), score_new,
                        MAC2STR(network->best_bss->bssid), score_best);
 
-               network->signal = bss->signal;
-               network->frequency = bss->frequency;
-               network->best_bss = bss;
+               update_network_with_best_bss(network, bss);
 
                SUPPLICANT_DBG("Update best BSS for %s", network->name);
 
@@ -2469,7 +2557,7 @@ static bool update_best_bss(GSupplicantNetwork *network,
 
        return false;
 }
-
+#endif
 static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 {
        GSupplicantInterface *interface = bss->interface;
@@ -2519,6 +2607,10 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        }
 
 #if defined TIZEN_EXT
+       network->owe_transition_mode = bss->owe_transition_mode;
+       memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
+       memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
+
        network->keymgmt = bss->keymgmt;
 
        if (g_slist_length(bss->vsie_list) > 0) {
@@ -2789,6 +2881,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        unsigned int value;
        int ie_len;
 #if defined TIZEN_EXT
+       const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c };
        int r_len, j;
        unsigned char *rates = NULL;
        unsigned char *ext_rates = NULL;
@@ -2827,8 +2920,41 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #if defined TIZEN_EXT
                unsigned char *vsie;
                int vsie_len = 0;
+
+               if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) {
+                       SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode");
+
+/*
+               Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode
+                       Tag Number: Vendor Specific (221)    -> ie[0]
+                       Tag length: 26                       -> ie[1]
+                       OUI: 50:6f:9a (Wi-Fi Alliance)       -> ie[2]
+                       Vendor Specific OUI Type: 28         -> ie[5]
+                       BSSID: 92:fd:f0:20:2b:09             -> ie[6]
+                       SSID length: 15                      -> ie[12]
+                       SSID: Wi-Fi-5.2.3-owe                -> ie[13]
+
+0000   dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d   ..Po..... +..Wi-
+0010   46 69 2d 35 2e 32 2e 33 2d 6f 77 65               Fi-5.2.3-owe
+
+*/
+                       bss->owe_transition_mode = TRUE;
+                       if (ie[1] >= 11) { // Tag length is at least up to ssid length position.
+                               memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX);
+                               if (ie[12] > 0 && ie[12] < 32) {
+                                       memcpy(bss->transition_mode_ssid, ie+13, ie[12]);
+                                       bss->transition_mode_ssid_len = ie[12];
+                               } else
+                                       bss->transition_mode_ssid_len = 0;
+                       } else
+                               bss->owe_transition_mode = FALSE;
+                       continue;
+               }
+
                if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
-                       SUPPLICANT_DBG("IE: match vendor specific data");
+
+                       if (!simplified_log)
+                               SUPPLICANT_DBG("IE: match vendor specific data");
 
                        vsie_len = ie[1]+2;     // tag number size(1), tag length size(1)
                        vsie = (unsigned char *)g_try_malloc0(vsie_len);
@@ -2994,7 +3120,7 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->sae)
                bss->security = G_SUPPLICANT_SECURITY_SAE;
-       else if (bss->owe)
+       else if (bss->owe || bss->owe_transition_mode)
                bss->security = G_SUPPLICANT_SECURITY_OWE;
        else if (bss->dpp)
                bss->security = G_SUPPLICANT_SECURITY_DPP;
@@ -3013,7 +3139,9 @@ static void bss_property(const char *key, DBusMessageIter *iter,
 
        if (!bss->interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key %s", key);
 
        if (!key)
@@ -3120,7 +3248,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
        GSupplicantNetwork *network;
        struct g_supplicant_bss *bss;
        const char *path = NULL;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        dbus_message_iter_get_basic(iter, &path);
@@ -3129,7 +3259,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
 
        if (g_strcmp0(path, "/") == 0)
                return NULL;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("%s", path);
 
        network = g_hash_table_lookup(interface->bss_mapping, path);
@@ -3154,7 +3286,9 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
                                                void *user_data)
 {
        struct g_supplicant_bss *bss;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
@@ -3185,7 +3319,9 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
                                                void *user_data)
 {
        struct g_supplicant_bss *bss;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
@@ -3418,7 +3554,9 @@ static void wps_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key: %s", key);
 
        if (g_strcmp0(key, "ConfigMethods") == 0) {
@@ -3441,6 +3579,21 @@ static void wps_property(const char *key, DBusMessageIter *iter,
 
 }
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+void g_supplicant_replace_config_file(const char *ifname, const char *config_file)
+{
+       if (!ifname)
+              return;
+
+       if (!config_file)
+               return;
+
+       SUPPLICANT_DBG("New {%s, %s}", ifname, config_file);
+       g_hash_table_replace(config_file_table,
+                       g_strdup(ifname), g_strdup(config_file));
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
 static void interface_property(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
 {
@@ -3448,7 +3601,9 @@ static void interface_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("%s", key);
 
        if (!key) {
@@ -3873,7 +4028,9 @@ static void signal_interface_removed(const char *path, DBusMessageIter *iter)
 static void signal_interface_changed(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
@@ -3923,7 +4080,9 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter)
 static void signal_bss_added(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
@@ -4015,6 +4174,40 @@ static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
        callback_sta_deauthorized(interface, addr);
 }
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static void signal_eap(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       const char *str = NULL;
+
+       SUPPLICANT_DBG("EAPOL_DEBUG callback eap signal");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       // TODO: Identify EAP fail condition, currently timeout is used for failure.
+
+       dbus_message_iter_get_basic(iter, &str);
+       if (!str)
+               return;
+
+       if (g_strcmp0("completion", str))
+               return;
+
+       dbus_message_iter_next(iter);
+
+       dbus_message_iter_get_basic(iter, &str);
+       if (!str)
+               return;
+
+       if (!g_strcmp0("success", str))
+               callback_eap(interface, true);
+       else
+               callback_eap(interface, false);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
@@ -4023,6 +4216,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        unsigned int old_wps_capabilities;
        struct g_supplicant_bss *bss;
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(bss_mapping, path);
@@ -5090,6 +5286,10 @@ static struct {
                signal_mesh_peer_disconnected },
 #endif
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+       { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap },
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
        { }
 };
 
@@ -5500,6 +5700,53 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data)
        supplicant_dbus_dict_close(iter, &dict);
 }
 
+#if defined TIZEN_EXT
+static void interface_get_state(const char *key, DBusMessageIter *iter,
+               void *user_data)
+{
+       struct interface_create_data *data = user_data;
+       GSupplicantInterface *interface = NULL;
+       const char *str = NULL;
+
+       SUPPLICANT_DBG("key[%s]", key);
+
+       if (!data) {
+               SUPPLICANT_DBG("data is NULL");
+               return;
+       }
+
+       interface = data->interface;
+       if (!interface) {
+               SUPPLICANT_DBG("interface is NULL");
+               return;
+       }
+
+       if (iter)
+               dbus_message_iter_get_basic(iter, &str);
+
+       if (str) {
+               if (string2state(str) != interface->state)
+                       interface->state = string2state(str);
+       }
+
+       if (interface->state == G_SUPPLICANT_STATE_DISABLED)
+               interface->ready = FALSE;
+       else
+               interface->ready = TRUE;
+
+       SUPPLICANT_DBG("state %s (%d)", str, interface->state);
+
+       if (data->callback) {
+               data->callback(0, interface, data->user_data);
+#if defined TIZEN_EXT_WIFI_MESH
+               callback_mesh_support(interface);
+#endif
+       }
+
+       interface_create_data_free(data);
+}
+#endif
+
 static void interface_get_result(const char *error,
                                DBusMessageIter *iter, void *user_data)
 {
@@ -5508,6 +5755,9 @@ static void interface_get_result(const char *error,
        const char *path = NULL;
        int err;
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        if (error) {
@@ -5527,6 +5777,16 @@ static void interface_get_result(const char *error,
                goto done;
        }
 
+#if defined TIZEN_EXT
+       data->interface = interface;
+       err = supplicant_dbus_property_get(path,
+                       SUPPLICANT_INTERFACE ".Interface",
+                       "State", interface_get_state, data, NULL);
+
+       if (err == 0)
+               return;
+#endif
+
        if (data->callback) {
                data->callback(0, interface, data->user_data);
 #if !defined TIZEN_EXT
@@ -5568,7 +5828,9 @@ done:
 static void interface_get_params(DBusMessageIter *iter, void *user_data)
 {
        struct interface_create_data *data = user_data;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
@@ -5764,7 +6026,6 @@ static void interface_remove_params(DBusMessageIter *iter, void *user_data)
                                                        &data->interface->path);
 }
 
-
 int g_supplicant_interface_remove(GSupplicantInterface *interface,
                        GSupplicantInterfaceCallback callback,
                                                        void *user_data)
@@ -6905,7 +7166,10 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
                add_network_security_proto(dict, ssid);
                break;
        case G_SUPPLICANT_SECURITY_SAE:
-               key_mgmt = "SAE";
+               if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK)
+                       key_mgmt = "SAE WPA-PSK"; // WFA (WPA3 & WPA2 Mixed -> WPA2 only)
+               else
+                       key_mgmt = "SAE";
                add_network_security_psk(dict, ssid);
                break;
        case G_SUPPLICANT_SECURITY_OWE:
@@ -6988,7 +7252,11 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                                                ssid->ssid_len);
 
 #if defined TIZEN_EXT
-       if (ssid->bssid) {
+       bool owe_transition_mode = FALSE;
+       if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE))
+               owe_transition_mode = TRUE;
+
+       if (ssid->bssid && !owe_transition_mode) {
                char *bssid = NULL;
                bssid = g_try_malloc0(18);
                if (bssid == NULL) {
@@ -8221,7 +8489,37 @@ void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bs
 }
 #endif
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb)
+{
+       SUPPLICANT_DBG("g_supplicant_register_eap_callback %p", cb);
+
+       if (!callbacks_pointer) {
+               SUPPLICANT_DBG("callbacks_pointer is NULL");
+               return;
+       }
+
+       callbacks_pointer->eap = cb;
+}
+
+void g_supplicant_unregister_eap_callback(void)
+{
+       SUPPLICANT_DBG("g_supplicant_unregister_eap_callback");
+
+       if (!callbacks_pointer) {
+               SUPPLICANT_DBG("callbacks_pointer is NULL");
+               return;
+       }
+
+       callbacks_pointer->eap = NULL;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+int g_supplicant_register(GSupplicantCallbacks *callbacks)
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 {
        connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
        if (!connection)
@@ -8233,7 +8531,9 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
                connection = NULL;
                return -EIO;
        }
-
+#if defined TIZEN_EXT
+       simplified_log = connman_setting_get_bool("SimplifiedLog");
+#endif
        callbacks_pointer = callbacks;
        eap_methods = 0;
 
@@ -8283,6 +8583,7 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        } else
                invoke_introspect_method();
 
+       SUPPLICANT_DBG("supplicant dbus setup completed");
        return 0;
 }