[connman] Added support to get WiFi vendor element.
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index 329bf6b..0d5ff3b 100755 (executable)
@@ -181,6 +181,9 @@ struct _GSupplicantInterface {
        GHashTable *bss_mapping;
        void *data;
        const char *pending_peer_path;
+#if defined TIZEN_EXT
+       int disconnect_reason;
+#endif
 };
 
 struct g_supplicant_bss {
@@ -205,6 +208,12 @@ struct g_supplicant_bss {
        dbus_bool_t privacy;
        dbus_bool_t psk;
        dbus_bool_t ieee8021x;
+#if defined TIZEN_EXT
+       dbus_bool_t ft_psk;
+       dbus_bool_t ft_ieee8021x;
+       char *wifi_vsie;
+       unsigned int wifi_vsie_len;
+#endif
        unsigned int wps_capabilities;
 };
 
@@ -229,6 +238,9 @@ struct _GSupplicantNetwork {
        char *eap;
        char *identity;
        char *phase2;
+       unsigned int keymgmt;
+       char *wifi_vsie;
+       unsigned int wifi_vsie_len;
 #endif
 };
 
@@ -316,6 +328,12 @@ static const char *security2string(GSupplicantSecurity security)
                return "psk";
        case G_SUPPLICANT_SECURITY_IEEE8021X:
                return "ieee8021x";
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_SECURITY_FT_PSK:
+               return "ft_psk";
+       case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
+               return "ft_ieee8021x";
+#endif
        }
 
        return NULL;
@@ -545,6 +563,20 @@ static void callback_peer_request(GSupplicantPeer *peer)
        callbacks_pointer->peer_request(peer);
 }
 
+static void callback_disconnect_reason_code(GSupplicantInterface *interface,
+                                       int reason_code)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->disconnect_reasoncode)
+               return;
+
+       if (reason_code != 0)
+               callbacks_pointer->disconnect_reasoncode(interface,
+                                                       reason_code);
+}
+
 static void remove_group(gpointer data)
 {
        GSupplicantGroup *group = data;
@@ -613,6 +645,10 @@ static void remove_network(gpointer data)
        g_free(network->identity);
        g_free(network->phase2);
 #endif
+#if defined TIZEN_EXT
+       g_free(network->wifi_vsie);
+#endif
+
        g_free(network);
 }
 
@@ -621,6 +657,9 @@ static void remove_bss(gpointer data)
        struct g_supplicant_bss *bss = data;
 
        g_free(bss->path);
+#if defined TIZEN_EXT
+       g_free(bss->wifi_vsie);
+#endif
        g_free(bss);
 }
 
@@ -1161,6 +1200,14 @@ const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
 
        return network->phase2;
 }
+
+unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return 0;
+
+       return network->keymgmt;
+}
 #endif
 
 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
@@ -1292,6 +1339,34 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
 
        return NULL;
 }
+
+bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return 0;
+
+       if (network->best_bss->rsn_selected) {
+               const char *mode = g_supplicant_network_get_enc_mode(network);
+               if (g_strcmp0(mode, "aes") == 0 ||
+                               g_strcmp0(mode, "mixed") == 0)
+                       return true;
+               else
+                       return false;
+       } else
+               return false;
+}
+
+const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network,
+                                               unsigned int *wifi_vsie_len)
+{
+       if (!network) {
+               *wifi_vsie_len = 0;
+               return NULL;
+       }
+
+       *wifi_vsie_len = network->wifi_vsie_len;
+       return network->wifi_vsie;
+}
 #endif
 
 static void merge_network(GSupplicantNetwork *network)
@@ -1584,6 +1659,21 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        network->frequency = bss->frequency;
        network->best_bss = bss;
 
+#if defined TIZEN_EXT
+       network->keymgmt = bss->keymgmt;
+
+       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");
+               }
+       }
+#endif
+
        SUPPLICANT_DBG("New network %s created", network->name);
 
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -1761,6 +1851,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;
@@ -1776,6 +1869,9 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #define WPS_PBC           0x04
 #define WPS_PIN           0x00
 #define WPS_CONFIGURED    0x02
+#if defined TIZEN_EXT
+#define VENDOR_SPECIFIC_INFO 0xDD
+#endif
 
        dbus_message_iter_recurse(iter, &array);
        dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
@@ -1788,7 +1884,19 @@ 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
+               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 ||
                        memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
                        continue;
@@ -1834,23 +1942,51 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
 
        bss->ieee8021x = FALSE;
        bss->psk = FALSE;
+#if defined TIZEN_EXT
+       bss->ft_ieee8021x = FALSE;
+       bss->ft_psk = FALSE;
+#endif
 
+#if defined TIZEN_EXT
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+                                       G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+               bss->ieee8021x = TRUE;
+       else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
+               bss->ft_ieee8021x = TRUE;
+#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
                bss->ieee8021x = TRUE;
+#endif
 
+#if defined TIZEN_EXT
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+                                       G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
+               bss->psk = TRUE;
+       else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
+               bss->ft_psk = TRUE;
+#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
                bss->psk = TRUE;
+#endif
 
        if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->psk)
                bss->security = G_SUPPLICANT_SECURITY_PSK;
+#if defined TIZEN_EXT
+       else if (bss->ft_psk)
+               bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
+       else if (bss->ft_ieee8021x == TRUE)
+               bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+#endif
        else if (bss->privacy)
                bss->security = G_SUPPLICANT_SECURITY_WEP;
        else
@@ -2204,6 +2340,9 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        } else if (g_strcmp0(key, "CurrentBSS") == 0) {
                interface_bss_added_without_keys(iter, interface);
        } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
+#if defined TIZEN_EXT
+               if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
+#endif
                interface_network_added(iter, interface);
        } else if (g_strcmp0(key, "BSSs") == 0) {
                supplicant_dbus_array_foreach(iter,
@@ -2214,6 +2353,12 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        } else if (g_strcmp0(key, "Networks") == 0) {
                supplicant_dbus_array_foreach(iter, interface_network_added,
                                                                interface);
+       } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+               int reason_code;
+               if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+                       dbus_message_iter_get_basic(iter, &reason_code);
+                       callback_disconnect_reason_code(interface, reason_code);
+               }
        } else
                SUPPLICANT_DBG("key %s type %c",
                                key, dbus_message_iter_get_arg_type(iter));
@@ -2247,15 +2392,30 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
+/*Fixed : stucking in scanning state when scan failed*/
+#if defined TIZEN_EXT
+               GSupplicantInterfaceCallback scan_callback;
+#endif
+
        if (iter)
                supplicant_dbus_array_foreach(iter, scan_network_update,
                                                interface);
 
+#if defined TIZEN_EXT
+               scan_callback = interface->scan_callback;
+#endif
+
        if (interface->scan_callback)
                interface->scan_callback(0, interface, interface->scan_data);
 
+#if defined TIZEN_EXT
+               if (interface->scan_callback == scan_callback) {
+#endif
        interface->scan_callback = NULL;
        interface->scan_data = NULL;
+#if defined TIZEN_EXT
+       }
+#endif
 }
 
 static GSupplicantInterface *interface_alloc(const char *path)
@@ -2582,7 +2742,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                return;
 
        supplicant_dbus_property_foreach(iter, bss_property, bss);
-
+#if defined TIZEN_EXT
+       network->frequency = bss->frequency;
+#endif
        old_security = network->security;
        bss_compute_security(bss);
 
@@ -4186,8 +4348,14 @@ static int interface_ready_to_scan(GSupplicantInterface *interface)
        case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
                return -EBUSY;
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_STATE_DISABLED:
+               return -ENOLINK;
+       case G_SUPPLICANT_STATE_UNKNOWN:
+#else
        case G_SUPPLICANT_STATE_UNKNOWN:
        case G_SUPPLICANT_STATE_DISABLED:
+#endif
        case G_SUPPLICANT_STATE_DISCONNECTED:
        case G_SUPPLICANT_STATE_INACTIVE:
        case G_SUPPLICANT_STATE_SCANNING:
@@ -4277,7 +4445,11 @@ static void interface_select_network_result(const char *error,
 
        err = 0;
        if (error) {
+#if defined TIZEN_EXT
+               SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
+#else
                SUPPLICANT_DBG("SelectNetwork error %s", error);
+#endif
                err = parse_supplicant_error(iter);
        }
 
@@ -4295,9 +4467,15 @@ static void interface_select_network_params(DBusMessageIter *iter,
 {
        struct interface_connect_data *data = user_data;
        GSupplicantInterface *interface = data->interface;
+#if defined TIZEN_EXT
+       GSupplicantSSID *ssid = data->ssid;
+#endif
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
                                        &interface->network_path);
+#if defined TIZEN_EXT
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
+#endif
 }
 
 static void interface_add_network_result(const char *error,
@@ -4320,11 +4498,23 @@ static void interface_add_network_result(const char *error,
        g_free(interface->network_path);
        interface->network_path = g_strdup(path);
 
+#if defined TIZEN_EXT
+       SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
+#endif
+
+#if defined TIZEN_EXT
+       supplicant_dbus_method_call(data->interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
+                       interface_select_network_params,
+                       interface_select_network_result, data,
+                       interface);
+#else
        supplicant_dbus_method_call(data->interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
                        interface_select_network_params,
                        interface_select_network_result, data,
                        interface);
+#endif
 
        return;
 
@@ -4490,8 +4680,10 @@ static void add_network_security_tls(DBusMessageIter *dict,
        if (!ssid->private_key_path)
                return;
 
+#if !defined TIZEN_EXT
        if (!ssid->private_key_passphrase)
                return;
+#endif
 
        if (ssid->ca_cert_path)
                supplicant_dbus_dict_append_basic(dict, "ca_cert",
@@ -4500,9 +4692,11 @@ static void add_network_security_tls(DBusMessageIter *dict,
        supplicant_dbus_dict_append_basic(dict, "private_key",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
+#if !defined TIZEN_EXT
        supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
+#endif
        supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
                                                &ssid->client_cert_path);
@@ -4534,8 +4728,10 @@ static void add_network_security_peap(DBusMessageIter *dict,
                if (!ssid->private_key_path)
                        return;
 
+#if !defined TIZEN_EXT
                if (!ssid->private_key_passphrase)
                        return;
+#endif
 
                supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
@@ -4545,9 +4741,11 @@ static void add_network_security_peap(DBusMessageIter *dict,
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
 
+#if !defined TIZEN_EXT
                supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
+#endif
 
        }
 
@@ -4573,6 +4771,19 @@ static void add_network_security_peap(DBusMessageIter *dict,
        g_free(phase2_auth);
 }
 
+#if defined TIZEN_EXT
+static void add_network_security_aka_sim(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       if (!ssid->passphrase)
+               return;
+
+       supplicant_dbus_dict_append_basic(dict, "password",
+                       DBUS_TYPE_STRING,
+                       &ssid->passphrase);
+}
+#endif
+
 static void add_network_security_eap(DBusMessageIter *dict,
                                        GSupplicantSSID *ssid)
 {
@@ -4598,6 +4809,7 @@ static void add_network_security_eap(DBusMessageIter *dict,
 #if defined TIZEN_EXT
        } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
                        g_strcmp0(ssid->eap, "aka") == 0) {
+               add_network_security_aka_sim(dict, ssid);
 #endif
        } else
                return;
@@ -4741,6 +4953,20 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
                add_network_security_ciphers(dict, ssid);
                add_network_security_proto(dict, ssid);
                break;
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_SECURITY_FT_PSK:
+               key_mgmt = "FT-PSK";
+               add_network_security_psk(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
+               key_mgmt = "FT-EAP";
+               add_network_security_eap(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+#endif
        }
 
        supplicant_dbus_dict_append_basic(dict, "key_mgmt",
@@ -4800,6 +5026,23 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                                        DBUS_TYPE_INT32,
                                        &ssid->ignore_broadcast_ssid);
 
+#if defined TIZEN_EXT
+       if (ssid->bssid) {
+               char *bssid = NULL;
+               bssid = g_try_malloc0(18);
+               if (bssid == NULL) {
+                       SUPPLICANT_DBG("memory allocation error");
+                       return;
+               }
+               snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                       ssid->bssid[0], ssid->bssid[1], ssid->bssid[2],
+                                       ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]);
+               supplicant_dbus_dict_append_basic(&dict, "bssid",
+                                       DBUS_TYPE_STRING, &bssid);
+               g_free(bssid);
+       }
+#endif
+
        supplicant_dbus_dict_close(iter, &dict);
 }
 
@@ -5519,6 +5762,28 @@ int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
        return -EINPROGRESS;
 }
 
+#if defined TIZEN_EXT
+int g_supplicant_interface_remove_network(GSupplicantInterface *interface)
+{
+       struct interface_data *data;
+
+       SUPPLICANT_DBG("");
+
+       if (interface == NULL)
+               return -EINVAL;
+
+       if (system_available == FALSE)
+               return -EFAULT;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->interface = interface;
+
+       return network_remove(data);
+}
+#endif
 
 static const char *g_supplicant_rule0 = "type=signal,"
                                        "path=" DBUS_PATH_DBUS ","