Modified way of update rssi value
[platform/core/connectivity/net-config.git] / src / wifi-ssid-scan.c
index 390fe1b..5e7fe37 100755 (executable)
@@ -17,6 +17,8 @@
  *
  */
 
+#include <stdio.h>
+
 #include "log.h"
 #include "util.h"
 #include "neterror.h"
 #include "wifi-ssid-scan.h"
 #include "wifi-background-scan.h"
 
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+#define WIFI_KEYMGMT_NONE                      (1 << 0)
+#define WIFI_KEYMGMT_IEEE8021X         (1 << 1)
+#define WIFI_KEYMGMT_WPA_NONE          (1 << 2)
+#define WIFI_KEYMGMT_WPA_PSK           (1 << 3)
+#define WIFI_KEYMGMT_WPA_PSK_256       (1 << 4)
+#define WIFI_KEYMGMT_WPA_FT_PSK                (1 << 5)
+#define WIFI_KEYMGMT_WPA_FT_EAP                (1 << 6)
+#define WIFI_KEYMGMT_WPA_EAP           (1 << 7)
+#define WIFI_KEYMGMT_WPA_EAP_256       (1 << 8)
+#define WIFI_KEYMGMT_WPS                       (1 << 9)
+
+#define WIFI_PAIRWISE_NONE                     (1 << 0)
+#define WIFI_PAIRWISE_TKIP                     (1 << 1)
+#define WIFI_PAIRWISE_CCMP                     (1 << 2)
+
+typedef struct {
+       const char *str;
+       unsigned int val;
+} strval_s;
+
+static strval_s wifi_keymgmt[] = {
+       { "none",                       WIFI_KEYMGMT_NONE },
+       { "ieee8021x",          WIFI_KEYMGMT_IEEE8021X },
+       { "wpa-none",           WIFI_KEYMGMT_WPA_NONE },
+       { "wpa-psk",            WIFI_KEYMGMT_WPA_PSK },
+       { "wpa-psk-sha256",     WIFI_KEYMGMT_WPA_PSK_256 },
+       { "wpa-ft-psk",         WIFI_KEYMGMT_WPA_FT_PSK },
+       { "wpa-ft-eap",         WIFI_KEYMGMT_WPA_FT_EAP },
+       { "wpa-eap",            WIFI_KEYMGMT_WPA_EAP },
+       { "wpa-eap-sha256",     WIFI_KEYMGMT_WPA_EAP_256 },
+       { "wps",                        WIFI_KEYMGMT_WPS },
+       { }
+};
+
+static strval_s wifi_pairwise[] = {
+       { "none",                       WIFI_PAIRWISE_NONE },
+       { "tkip",                       WIFI_PAIRWISE_TKIP },
+       { "ccmp",                       WIFI_PAIRWISE_CCMP },
+       { }
+};
+
 typedef enum {
        WIFI_SECURITY_UNKNOWN = 0x00,
-       WIFI_SECURITY_NONE = 0x01,
-       WIFI_SECURITY_WEP = 0x02,
-       WIFI_SECURITY_PSK = 0x03,
-       WIFI_SECURITY_IEEE8021X = 0x04,
+       WIFI_SECURITY_NONE,
+       WIFI_SECURITY_WEP,
+       WIFI_SECURITY_PSK,
+       WIFI_SECURITY_PSK2,
+       WIFI_SECURITY_IEEE8021X,
 } wifi_security_e;
 
 typedef struct {
        unsigned char ssid[33];
+       unsigned char bssid[6];
        wifi_security_e security;
+       unsigned int wpa_keymgmt;
+       unsigned int wpa_pairwise;
+       unsigned int rsn_keymgmt;
+       unsigned int rsn_pairwise;
+       gboolean rsn_selected;
        gboolean privacy;
        gboolean wps;
 } bss_info_t;
@@ -45,27 +98,67 @@ static GSList *bss_info_list = NULL;
 static guint ssid_scan_timer = 0;
 static char *g_ssid = NULL;
 
-static void __check_security(const char *str_keymgmt, bss_info_t *bss_info)
+static void __check_keymgmt(const char *str_keymgmt, unsigned int *key_info)
 {
-       INFO("keymgmt : %s", str_keymgmt);
+       int i;
+
+       for (i = 0; wifi_keymgmt[i].str; i++) {
+               if (g_strcmp0(str_keymgmt, wifi_keymgmt[i].str) == 0) {
+                       INFO("keymgmt : %s", str_keymgmt);
+                       *key_info |= wifi_keymgmt[i].val;
+                       break;
+               }
+       }
+}
 
-       if (g_strcmp0(str_keymgmt, "ieee8021x") == 0) {
+static void __check_pairwise(const char *str_pairwise, unsigned int *pairwise_info)
+{
+       int i;
+
+       for (i = 0; wifi_pairwise[i].str; i++) {
+               if (g_strcmp0(str_pairwise, wifi_pairwise[i].str) == 0) {
+                       INFO("pairwise : %s", str_pairwise);
+                       *pairwise_info |= wifi_pairwise[i].val;
+                       break;
+               }
+       }
+}
+
+static wifi_security_e __check_security(bss_info_t *bss_info)
+{
+       gboolean ieee8021x = FALSE;
+       gboolean psk = FALSE;
+       gboolean ft_ieee8021x = FALSE;
+       gboolean ft_psk = FALSE;
+       unsigned int keymgmt = bss_info->rsn_keymgmt | bss_info->wpa_keymgmt;
+
+       if (keymgmt & (WIFI_KEYMGMT_WPA_EAP | WIFI_KEYMGMT_WPA_EAP_256))
+               ieee8021x = TRUE;
+       else if (keymgmt & WIFI_KEYMGMT_WPA_FT_EAP)
+               ft_ieee8021x = TRUE;
+
+       if (keymgmt & (WIFI_KEYMGMT_WPA_PSK | WIFI_KEYMGMT_WPA_PSK_256))
+               psk = TRUE;
+       else if (keymgmt & WIFI_KEYMGMT_WPA_FT_PSK)
+               ft_psk = TRUE;
+
+       if (ieee8021x || ft_ieee8021x)
                bss_info->security = WIFI_SECURITY_IEEE8021X;
-       } else if (g_strcmp0(str_keymgmt, "wpa-psk") == 0) {
-               bss_info->security = WIFI_SECURITY_PSK;
-       } else if (g_strcmp0(str_keymgmt, "wpa-psk-sha256") == 0) {
-               bss_info->security = WIFI_SECURITY_PSK;
-       } else if (g_strcmp0(str_keymgmt, "wpa-ft-psk") == 0) {
+       else if (psk || ft_psk)
                bss_info->security = WIFI_SECURITY_PSK;
-       } else if (g_strcmp0(str_keymgmt, "wpa-ft-eap") == 0) {
-               bss_info->security = WIFI_SECURITY_IEEE8021X;
-       } else if (g_strcmp0(str_keymgmt, "wpa-eap") == 0) {
-               bss_info->security = WIFI_SECURITY_IEEE8021X;
-       } else if (g_strcmp0(str_keymgmt, "wpa-eap-sha256") == 0) {
-               bss_info->security = WIFI_SECURITY_IEEE8021X;
-       } else if (g_strcmp0(str_keymgmt, "wps") == 0) {
-               bss_info->wps = TRUE;
+       else if (bss_info->privacy)
+               bss_info->security = WIFI_SECURITY_WEP;
+       else
+               bss_info->security = WIFI_SECURITY_NONE;
+
+       if (bss_info->rsn_selected) {
+               unsigned int pairwise = bss_info->rsn_pairwise | bss_info->wpa_pairwise;
+               if ((pairwise & WIFI_PAIRWISE_CCMP) ||
+                       (pairwise & (WIFI_PAIRWISE_CCMP | WIFI_PAIRWISE_TKIP)))
+                       bss_info->security = WIFI_SECURITY_PSK2;
        }
+
+       return bss_info->security;
 }
 
 static gboolean __ssid_scan_timeout(gpointer data)
@@ -91,7 +184,7 @@ static void _stop_ssid_scan_timer(void)
        netconfig_stop_timer(&ssid_scan_timer);
 }
 
-static void _parse_keymgmt_message(GVariant *param, bss_info_t *bss_info)
+static void _parse_wpa_message(GVariant *param, bss_info_t *bss_info)
 {
        GVariantIter *iter1;
        GVariant *var;
@@ -99,21 +192,40 @@ static void _parse_keymgmt_message(GVariant *param, bss_info_t *bss_info)
 
        g_variant_get(param, "a{sv}", &iter1);
        while (g_variant_iter_loop(iter1, "{sv}", &key, &var)) {
-               if (g_strcmp0(key, "KeyMgmt") == 0) {//check this :iterate
+               if (g_strcmp0(key, "KeyMgmt") == 0) {
+                       GVariantIter *iter2;
+                       g_variant_get(var, "as", &iter2);
+                       char *str;
+                       while (g_variant_iter_loop(iter2, "s", &str)) {
+                               if (str == NULL)
+                                       break;
+                               unsigned int key_info = 0;
+                               __check_keymgmt(str, &key_info);
+                               if (bss_info->rsn_selected)
+                                       bss_info->rsn_keymgmt = key_info;
+                               else
+                                       bss_info->wpa_keymgmt = key_info;
+                       }
+                       g_variant_iter_free(iter2);
+               } else if (g_strcmp0(key, "Pairwise") == 0) {
                        GVariantIter *iter2;
                        g_variant_get(var, "as", &iter2);
                        char *str;
                        while (g_variant_iter_loop(iter2, "s", &str)) {
-                               if (str == NULL) {
+                               if (str == NULL)
                                        break;
-                               }
-                               __check_security(str, bss_info);
+                               unsigned int pairwise_info = 0;
+                               __check_pairwise(str, &pairwise_info);
+                               if (bss_info->rsn_selected)
+                                       bss_info->rsn_pairwise = pairwise_info;
+                               else
+                                       bss_info->wpa_pairwise = pairwise_info;
                        }
-                       g_variant_iter_free (iter2);
+                       g_variant_iter_free(iter2);
                }
        }
 
-       g_variant_iter_free (iter1);
+       g_variant_iter_free(iter1);
 
        return;
 }
@@ -122,7 +234,6 @@ static gboolean _request_ssid_scan(const char *object_path, const char *ssid)
 {
        /* TODO: Revise following code */
 
-#define NETCONFIG_DBUS_REPLY_TIMEOUT (10 * 1000)
        GDBusConnection *connection = NULL;
        GVariant *reply = NULL;
        GVariant *params = NULL;
@@ -141,15 +252,14 @@ static gboolean _request_ssid_scan(const char *object_path, const char *ssid)
                return FALSE;
        }
 
-       builder1 = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        g_variant_builder_add(builder1, "{sv}", key1, g_variant_new_string(val1));
 
-       builder2 = g_variant_builder_new(G_VARIANT_TYPE ("aay"));
-       builder3 = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("aay"));
+       builder3 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
 
-       for (i = 0; i < strlen(ssid); i++) {
-               g_variant_builder_add (builder3, "y", ssid[i]);
-       }
+       for (i = 0; i < strlen(ssid); i++)
+               g_variant_builder_add(builder3, "y", ssid[i]);
 
        g_variant_builder_add(builder2, "@ay", g_variant_builder_end(builder3));
        g_variant_builder_add(builder1, "{sv}", key2, g_variant_builder_end(builder2));
@@ -184,9 +294,8 @@ static gboolean _request_ssid_scan(const char *object_path, const char *ssid)
                return FALSE;
        }
 
-       if (g_ssid != NULL) {
+       if (g_ssid != NULL)
                g_free(g_ssid);
-       }
 
        g_ssid = g_strdup(ssid);
 
@@ -200,18 +309,29 @@ static void _emit_ssid_scan_completed(void)
        GVariantBuilder *builder = NULL;
        GSList* list = NULL;
        const char *prop_ssid = "ssid";
+       const char *prop_bssid = "bssid";
+       char bssid_buf[18] = {0,};
+       char *bssid_str = bssid_buf;
        const char *prop_security = "security";
        const char *prop_wps = "wps";
 
-       builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        for (list = bss_info_list; list != NULL; list = list->next) {
                bss_info_t *bss_info = (bss_info_t *)list->data;
                if (bss_info && g_strcmp0((char *)bss_info->ssid, g_ssid) == 0) {
                        const gchar *ssid = (char *)bss_info->ssid;
-                       wifi_security_e security = bss_info->security;
+                       const gchar *bssid = (gchar *)&bss_info->bssid[0];
+                       wifi_security_e security = __check_security(bss_info);
                        gboolean wps = bss_info->wps;
                        DBG("BSS found; SSID:%s security:%d WPS:%d", ssid, security, wps);
+
+                       if (bssid) {
+                               snprintf(bssid_str, sizeof(bssid_buf), MACSTR, MAC2STR(bssid));
+                               DBG("BSSID: %s", bssid_str);
+                       }
                        g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
+                       g_variant_builder_add(builder, "{sv}", prop_bssid,
+                                               g_variant_new_string(bssid));
                        g_variant_builder_add(builder, "{sv}", prop_security, g_variant_new_int32(security));
                        /* WPS */
                        g_variant_builder_add(builder, "{sv}", prop_wps, g_variant_new_boolean(wps));
@@ -246,9 +366,8 @@ gboolean wifi_ssid_scan(const char *ssid)
        netconfig_wifi_bgscan_stop();
 
        if (ssid != NULL) {
-               if (scan_ssid != NULL) {
+               if (scan_ssid != NULL)
                        g_free(scan_ssid);
-               }
                scan_ssid = g_strdup(ssid);
        }
 
@@ -263,7 +382,6 @@ gboolean wifi_ssid_scan(const char *ssid)
 
        if (netconfig_wifi_get_scanning() == TRUE) {
                DBG("Wi-Fi scan in progress, %s scan will be delayed", scan_ssid);
-               g_free(scan_ssid);
                return TRUE;
        }
 
@@ -303,6 +421,7 @@ void wifi_ssid_scan_emit_scan_completed(void)
 
        _stop_ssid_scan_timer();
        _emit_ssid_scan_completed();
+       netconfig_wifi_bgscan_start(FALSE);
 }
 
 void wifi_ssid_scan_add_bss(GVariant *message)
@@ -324,7 +443,7 @@ void wifi_ssid_scan_add_bss(GVariant *message)
        }
 
        if (path != NULL)
-               INFO("Object path of BSS added is %s",path);
+               INFO("Object path of BSS added is %s", path);
 
        bss_info = g_try_new0(bss_info_t, 1);
        if (bss_info == NULL)
@@ -344,13 +463,24 @@ void wifi_ssid_scan_add_bss(GVariant *message)
                        gboolean privacy = FALSE;
                        privacy = g_variant_get_boolean(value);
                        bss_info->privacy = privacy;
-               } else if ((g_strcmp0(key, "RSN") == 0) || (g_strcmp0(key, "WPA") == 0)) {
-                       _parse_keymgmt_message(value, bss_info);
+               } else if (g_strcmp0(key, "RSN") == 0) {
+                       bss_info->rsn_selected = TRUE;
+                       _parse_wpa_message(value, bss_info);
+               } else if (g_strcmp0(key, "WPA") == 0) {
+                       bss_info->rsn_selected = FALSE;
+                       _parse_wpa_message(value, bss_info);
                } else if (g_strcmp0(key, "IEs") == 0) {
                        const guchar *ie;
                        gsize ie_len;
                        ie = g_variant_get_fixed_array(value, &ie_len, sizeof(guchar));
-                       DBG("The IE : %s",ie);
+                       DBG("The IE : %s", ie);
+               } else if (g_strcmp0(key, "BSSID") == 0) {
+                       const guchar *bssid;
+                       gsize bssid_len;
+
+                       bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
+                       if (bssid != NULL && bssid_len == 6)
+                               memcpy(bss_info->bssid, bssid, bssid_len);
                }
        }
 
@@ -383,11 +513,10 @@ gboolean handle_request_specific_scan(Wifi *wifi,
 
        result = wifi_ssid_scan((const char *)ssid);
 
-       if (result != TRUE) {
+       if (result != TRUE)
                netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "FailSpecificScan");
-       } else {
-               wifi_complete_request_wps_scan(wifi, context);
-       }
+       else
+               wifi_complete_request_specific_scan(wifi, context);
 
        return result;
 }