Merge tag 'upstream/1.40' into tizen.
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index 6c997ba..c76c142 100755 (executable)
@@ -54,7 +54,6 @@
 #define WLAN_EID_SUPP_RATES 1
 #define WLAN_EID_EXT_SUPP_RATES 50
 #define COUNTRY_CODE_LENGTH    2
-#define WIFI_BSSID_LEN_MAX 6
 #endif
 
 #if defined TIZEN_EXT
@@ -318,6 +317,7 @@ struct g_supplicant_bss {
        unsigned int transition_mode_ssid_len;
        unsigned char transition_mode_bssid[6];
        unsigned char transition_mode_ssid[32];
+       dbus_bool_t pmf_required;
 #endif
 };
 
@@ -347,6 +347,7 @@ struct _GSupplicantNetwork {
        unsigned char country_code[COUNTRY_CODE_LENGTH];
        GSupplicantPhy_mode phy_mode;
        dbus_bool_t owe_transition_mode;
+       dbus_bool_t privacy;
        unsigned int transition_mode_ssid_len;
        unsigned char transition_mode_bssid[6];
        unsigned char transition_mode_ssid[32];
@@ -436,23 +437,6 @@ struct interface_scan_data {
 };
 
 #if defined TIZEN_EXT
-struct g_connman_bssids {
-       unsigned char bssid[WIFI_BSSID_LEN_MAX];
-       uint16_t strength;
-       uint16_t frequency;
-       uint16_t assoc_reject_cnt;
-       bool is_last_connected;
-#if defined TIZEN_EXT_INS
-       int score_last_connected_bssid;
-       int score_assoc_reject;
-       int score_frequency;
-       int score_strength;
-       int score_snr;
-       int score_est_throughput;
-#endif
-       int ins_score;
-};
-
 struct update_bssid_data {
        GSupplicantNetwork *network;
        unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
@@ -683,6 +667,9 @@ static int store_network_information(GSupplicantInterface * interface,
 
        if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
                ssid->security == G_SUPPLICANT_SECURITY_PSK ||
+#if defined TIZEN_EXT
+               ssid->security == G_SUPPLICANT_SECURITY_SAE ||
+#endif
                ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
                ssid->passphrase) {
                interface->network_info.passphrase = g_strdup(ssid->passphrase);
@@ -1435,6 +1422,14 @@ bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *inter
 
        return interface->is_5_0_Ghz_supported;
 }
+
+unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return NULL;
+
+       return (unsigned char *)interface->add_network_bssid;
+}
 #endif
 
 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
@@ -1748,12 +1743,20 @@ const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
 
 unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return 0;
 
        return network->keymgmt;
 }
 
+dbus_bool_t g_supplicant_network_get_privacy(GSupplicantNetwork *network)
+{
+       if (!network)
+               return FALSE;
+
+       return network->privacy;
+}
+
 const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
                                                          *network)
 {
@@ -1762,6 +1765,14 @@ const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
 
        return network->country_code;
 }
+
+dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network)
+{
+       if (!network)
+               return 0;
+
+       return network->best_bss->pmf_required;
+}
 #endif
 
 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
@@ -1900,10 +1911,10 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
                return NULL;
 
        if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
-           network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
-           network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
-           network->best_bss->security == G_SUPPLICANT_SECURITY_DPP ||
-           network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_DPP ||
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
                unsigned int pairwise;
 
                pairwise = network->best_bss->rsn_pairwise |
@@ -1930,8 +1941,7 @@ bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
        if (network == NULL || network->best_bss == NULL)
                return 0;
 
-       if (network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
-                       network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
+       if (network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
                        network->best_bss->security == G_SUPPLICANT_SECURITY_DPP)
                return false;
 
@@ -2125,7 +2135,6 @@ static int calculate_score_est_throughput(dbus_uint32_t est_throughput)
 
        return score;
 }
-#endif
 
 static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
                dbus_uint16_t frequency, dbus_int16_t strength,
@@ -2142,6 +2151,7 @@ static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
 
        return score;
 }
+#endif
 
 static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
 {
@@ -2161,6 +2171,7 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
                        bssids->strength = 100;
 
                bssids->frequency = bss->frequency;
+               bssids->score_snr = (int)bss->snr;
 
 #if defined TIZEN_EXT_INS
                bssids->assoc_reject_cnt = get_assoc_reject_cnt(bssid_data->assoc_reject_table, bssids->bssid);
@@ -2169,8 +2180,7 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
                bssids->score_last_connected_bssid = calculate_score_last_connected_bssid(bssids->is_last_connected);
                bssids->score_assoc_reject = calculate_score_assoc_reject(bssids->assoc_reject_cnt);
                bssids->score_frequency = calculate_score_frequency(bss->signal, bssids->frequency);
-               bssids->score_strength = calculate_score_strength(bssids->strength);
-               bssids->score_snr = (int)bss->snr;
+               bssids->score_strength = calculate_score_strength(bss->signal);
                bssids->score_est_throughput = calculate_score_est_throughput(bss->est_throughput);
 
                bssids->ins_score = calculate_score(bssids->is_last_connected,
@@ -2545,6 +2555,12 @@ static char *create_group(struct g_supplicant_bss *bss)
 static void update_network_with_best_bss(GSupplicantNetwork *network,
                struct g_supplicant_bss *best_bss)
 {
+       /*
+        * Do not change best BSS if we are connected.
+        */
+       if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED)
+               return;
+
        network->signal = best_bss->signal;
        network->frequency = best_bss->frequency;
        network->best_bss = best_bss;
@@ -2642,6 +2658,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 
 #if defined TIZEN_EXT
        network->owe_transition_mode = bss->owe_transition_mode;
+       network->privacy = bss->privacy;
        memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
        memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
 
@@ -2921,6 +2938,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        unsigned char *ext_rates = NULL;
        unsigned int max_rate = 0;
        unsigned int max_ext_rate = 0;
+       unsigned int offset = 0;
        bool ht = false;
        bool vht = false;
 #endif
@@ -2938,6 +2956,8 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #if defined TIZEN_EXT
 #define VENDOR_SPECIFIC_INFO 0xDD
 #define WLAN_EID_COUNTRY 7
+#define WLAN_EID_RSN_INFO 48
+#define RSN_CAPABILITY_MFP_REQ (1 << 6)
 #endif
 
        dbus_message_iter_recurse(iter, &array);
@@ -2955,7 +2975,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
                unsigned char *vsie;
                int vsie_len = 0;
 
-               if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 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");
 
 /*
@@ -2985,7 +3005,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
                        continue;
                }
 
-               if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
+               if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
 
                        if (!simplified_log)
                                SUPPLICANT_DBG("IE: match vendor specific data");
@@ -3001,7 +3021,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
                        continue;
                }
 
-               if(ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
+               if (ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
                        /* Add country code only if it is a valid alphabet */
                        if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) {
                                memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH);
@@ -3046,6 +3066,18 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
                        }
                        continue;
                }
+
+               if (ie[0] == WLAN_EID_RSN_INFO && ie[1] >= 20) {
+                       r_len = ie[1];
+                       offset = 10 + ie[8] * 4;
+                       offset += ie[offset] * 4 + 2;
+
+                       if (offset <= r_len + 1 &&
+                                       (ie[offset] & RSN_CAPABILITY_MFP_REQ) != 0)
+                               bss->pmf_required = TRUE;
+
+                       continue;
+               }
 #endif
                if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
                        memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
@@ -3146,6 +3178,8 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
        if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
 #if defined TIZEN_EXT
+       else if (bss->ft_ieee8021x)
+               bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->sae)
                bss->security = G_SUPPLICANT_SECURITY_SAE;
 #endif
@@ -3154,8 +3188,6 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
 #if defined TIZEN_EXT
        else if (bss->ft_psk)
                bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
-       else if (bss->ft_ieee8021x == TRUE)
-               bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->owe || bss->owe_transition_mode)
                bss->security = G_SUPPLICANT_SECURITY_OWE;
        else if (bss->dpp)
@@ -3510,6 +3542,11 @@ static void interface_current_bss(GSupplicantInterface *interface,
 
                network->best_bss = bss;
 
+#if defined TIZEN_EXT
+               if (network->frequency != bss->frequency)
+                       network->frequency = bss->frequency;
+#endif
+
                if (network->signal != bss->signal) {
                        SUPPLICANT_DBG("New network signal %d dBm",
                                                bss->signal);
@@ -3517,6 +3554,10 @@ static void interface_current_bss(GSupplicantInterface *interface,
                        network->signal = bss->signal;
                        callback_network_changed(network, "Signal");
                }
+#if defined TIZEN_EXT
+               else
+                       callback_network_changed(network, "");
+#endif
        }
 
        /*
@@ -4283,8 +4324,10 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        supplicant_dbus_property_foreach(iter, bss_property, bss);
 
 #if defined TIZEN_EXT
-       network->frequency = bss->frequency;
-       network->phy_mode = bss->phy_mode;
+       if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) {
+               network->frequency = bss->frequency;
+               network->phy_mode = bss->phy_mode;
+       }
 #endif
        old_security = network->security;
        bss_compute_security(bss);
@@ -5401,7 +5444,7 @@ static void country_result(const char *error,
                regdom->callback(result, regdom->alpha2,
                                        (void *) regdom->user_data);
 
-       dbus_free(regdom);
+       g_free(regdom);
 }
 
 static void country_params(DBusMessageIter *iter, void *user_data)
@@ -5665,7 +5708,7 @@ static void interface_create_result(const char *error,
        SUPPLICANT_DBG("");
 
        if (error) {
-               g_message("error %s", error);
+               g_warning("error %s", error);
                err = -EIO;
                goto done;
        }
@@ -6430,6 +6473,7 @@ static void interface_signalpoll_result(const char *error,
        int err = 0;
        dbus_int32_t maxspeed = 0;
        dbus_int32_t strength = 0;
+       dbus_int32_t snr = 0;
        DBusMessageIter sub_iter, dict;
 
        if (error) {
@@ -6466,6 +6510,10 @@ static void interface_signalpoll_result(const char *error,
                                dbus_message_iter_get_basic(&value, &strength);
                                SUPPLICANT_DBG("Strength = %d", strength);
                                break;
+                       } else if (g_strcmp0(key, "SNR") == 0) {
+                               dbus_message_iter_get_basic(&value, &snr);
+                               SUPPLICANT_DBG("SNR = %d", snr);
+                               break;
                        }
                }
                dbus_message_iter_next(&dict);
@@ -6473,7 +6521,7 @@ static void interface_signalpoll_result(const char *error,
 
 out:
        if(data->callback)
-               data->callback(err, maxspeed, strength, data->user_data);
+               data->callback(err, maxspeed, strength, snr, data->user_data);
 
        g_free(data->path);
        dbus_free(data);