Set netlink scan handle in non-blocking state
[platform/core/connectivity/net-config.git] / src / wifi-netlink-scan.c
index 3ad72c5..f4fb530 100755 (executable)
 #include <ctype.h>
 
 static GSList *bss_info_list = NULL;
-static unsigned char samsung_oui[3] = {0x00, 0x16, 0x32};
 
 void __netconfig_notify_netlink_scan_done(void)
 {
        GVariantBuilder *builder = NULL;
+       GVariantBuilder *builder1 = NULL;
+       GVariantBuilder *builder2 = NULL;
        GSList* list = NULL;
        const char *prop_ssid = "ssid";
        const char *prop_bssid = "bssid";
        const char *prop_freq = "freq";
        const char *prop_rssi = "rssi";
-       const char *prop_vsie = "vsie";
+       const char *prop_vsie_list = "vsie_list";
        const char *prop_sec = "security";
        const char *prop_enc = "encryption";
 
@@ -54,7 +55,7 @@ void __netconfig_notify_netlink_scan_done(void)
                if (bss_info) {
                        char *bssid = (char *)bss_info->bssid;
                        char *ssid = (char *)bss_info->ssid;
-                       char *vsie = (char *)bss_info->vsie;
+                       GSList *vsie_list = bss_info->vsie_list;
                        int freq = (int)bss_info->freq;
                        int signal = (int)bss_info->signal;
                        int sec_type = (int)bss_info->security_type;
@@ -64,7 +65,31 @@ void __netconfig_notify_netlink_scan_done(void)
                        g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid));
                        g_variant_builder_add(builder, "{sv}", prop_freq, g_variant_new_int32(freq));
                        g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(signal));
-                       g_variant_builder_add(builder, "{sv}", prop_vsie, g_variant_new_string(vsie));
+                       builder1 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+                       GSList *list;
+                       unsigned char *net_vsie;
+                       unsigned int net_vsie_len;
+                       int count;
+                       for (list = vsie_list; list; list = list->next) {
+                               builder2 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+                               net_vsie = (unsigned char *)list->data;
+                               net_vsie_len = net_vsie[1] + 2;
+
+                               for (count = 0; count < net_vsie_len; count++) {
+                                       g_variant_builder_add(builder2, "y", net_vsie[count]);
+                               }
+
+                               g_variant_builder_add(builder1, "{sv}", "Vsie", g_variant_builder_end(builder2));
+                               g_variant_builder_unref(builder2);
+                       }
+                       g_variant_builder_add(builder, "{sv}", prop_vsie_list, g_variant_builder_end(builder1));
+                       g_variant_builder_unref(builder1);
+
+                       if (vsie_list != NULL)
+                               g_slist_free_full(vsie_list, g_free);
+
+                       vsie_list = NULL;
+
                        g_variant_builder_add(builder, "{sv}", prop_sec, g_variant_new_int32(sec_type));
                        g_variant_builder_add(builder, "{sv}", prop_enc, g_variant_new_int32(enc_type));
                }
@@ -86,6 +111,7 @@ static int ack_handler(struct nl_msg *msg, void *user_data)
 {
        int *err = user_data;
        *err = 0;
+       DBG("");
        return NL_STOP;
 }
 
@@ -386,42 +412,30 @@ static void __netconfig_get_security(unsigned char *bss_element, int length, wif
        return;
 }
 
-static void __netconfig_get_vsie(unsigned char *bss_element, int length, char **dst)
+static void __netconfig_get_vsie(unsigned char *bss_element, int length, GSList **dst)
 {
-       int i = 0;
-       uint8_t len = 0;
-       gboolean vsie_found = FALSE;
+       unsigned char *vsie;
+       int vsie_len = 0;
 
        if (length < 3) {
                DBG("Vendor specific data not available");
                return;
        }
 
-       /** Check for vendor specific information element */
-       for (i = 0; i < length; i++) {
-               if (bss_element[i] == 221) {
-                       len = bss_element[i+1];
-                       vsie_found = TRUE;
-                       goto out;
-               }
-       }
-out:
-       if (vsie_found && memcmp(bss_element+i+2, samsung_oui, 3) == 0) {
-               DBG("Vendor Specific IE found, len: %d", len);
-               *dst = g_try_malloc0(2*(len+2) + 1);
-               if (*dst == NULL) {
-                       DBG("Failed to allocate memory");
-                       return;
-               }
-               char *buf = (*dst);
-               int j = 0;
-
-               for (j = i; j <= (i + len + 1); j++) {
-                       snprintf(buf, 3, "%02x", bss_element[j]);
-                       buf += 2;
+       while (length >= 2 && length >= bss_element[1]) {
+               if (bss_element[0] == NETCONFIG_VENDOR_SPECIFIC_ID) {
+                       vsie_len = bss_element[1]+2;
+                       vsie = (unsigned char *)g_try_malloc0(vsie_len);
+
+                       if (vsie) {
+                               memcpy(vsie, bss_element, vsie_len);
+                               *dst = g_slist_append(*dst, vsie);
+                       } else
+                               DBG("Failed to allocate memory");
                }
 
-               vsie_found = FALSE;
+               length -= bss_element[1] + 2;
+               bss_element += bss_element[1] + 2;
        }
 }
 
@@ -458,7 +472,7 @@ static int __netconfig_netlink_scan_cb(struct nl_msg *msg, void *user_data)
        char ssid[NETCONFIG_SSID_LEN+1] = {0, };
        wifi_security_type_e sec_type = WIFI_SECURITY_TYPE_NONE;
        wifi_encryption_type_e enc_type = WIFI_ENCRYPTION_TYPE_NONE;
-       char *vsie = NULL;
+       GSList *vsie = NULL;
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
        struct nlattr *bss[NL80211_BSS_MAX + 1];
        struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
@@ -488,13 +502,15 @@ static int __netconfig_netlink_scan_cb(struct nl_msg *msg, void *user_data)
        __netconfig_get_security(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
                        nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), &sec_type, &enc_type);
 
-       if (sec_type == WIFI_SECURITY_TYPE_EAP)
+       if (sec_type == WIFI_SECURITY_TYPE_EAP) {
+               g_slist_free_full(vsie, g_free);
                return NL_SKIP;
+       }
        for (GSList *list = bss_info_list; list != NULL; list = list->next) {
                struct bss_scan_info_t *bss_info = (struct bss_scan_info_t *)list->data;
                if ((g_strcmp0(bss_info->ssid, ssid) == 0) && (bss_info->security_type == sec_type)
                                && (bss_info->encryption_type == enc_type)) {
-                       g_free(vsie);
+                       g_slist_free_full(vsie, g_free);
                        return NL_SKIP;
                }
        }
@@ -506,17 +522,13 @@ static int __netconfig_netlink_scan_cb(struct nl_msg *msg, void *user_data)
 
                bss_info = g_try_new0(struct bss_scan_info_t, 1);
                if (bss_info == NULL) {
-                       g_free(vsie);
+                       g_slist_free_full(vsie, g_free);
                        return NL_SKIP;
                }
 
                g_strlcpy(bss_info->bssid, bssid, strlen(bssid)+1);
                g_strlcpy(bss_info->ssid, ssid, strlen(ssid)+1);
-               if (vsie) {
-                       g_strlcpy(bss_info->vsie, vsie, strlen(vsie)+1);
-                       g_free(vsie);
-                       vsie = NULL;
-               }
+               bss_info->vsie_list = vsie;
                bss_info->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
 
                if (bss[NL80211_BSS_SIGNAL_MBM]) {
@@ -527,18 +539,18 @@ static int __netconfig_netlink_scan_cb(struct nl_msg *msg, void *user_data)
 
                bss_info->security_type = sec_type;
                bss_info->encryption_type = enc_type;
-               DBG("%s %d %d %s %d %d [vsie: %s]", bss_info->bssid, bss_info->freq,
+               DBG("%s %d %d %s %d %d ", bss_info->bssid, bss_info->freq,
                                bss_info->signal, bss_info->ssid, bss_info->security_type,
-                               bss_info->encryption_type, bss_info->vsie);
+                               bss_info->encryption_type);
 
                if (bss_info->ssid[0] == '\0')
                        g_free(bss_info);
                else
                        bss_info_list = g_slist_append(bss_info_list, bss_info);
 
-       }
+       } else
+               g_slist_free_full(vsie, g_free);
 
-       g_free(vsie);
        return NL_SKIP;
 }
 
@@ -669,9 +681,12 @@ static int __netconfig_request_netlink_scan(struct nl_sock *socket,
        nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
        nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
        nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+       ret = nl_socket_set_nonblocking(socket);
+       DBG("Set the non-blocking mode [%d]", ret);
 
        /** Send NL80211_CMD_TRIGGER_SCAN to start the scan. */
        ret = nl_send_auto_complete(socket, msg);
+
        if (ret < 0) {
                DBG("nl_send_auto_complete() error: (%s)", nl_geterror(-ret));
                goto out;
@@ -680,19 +695,26 @@ static int __netconfig_request_netlink_scan(struct nl_sock *socket,
        DBG("Sent %d bytes to the kernel", ret);
        ssid_found = FALSE;
 
-       while (err > 0)
+       while (err > 0) {
                ret = nl_recvmsgs(socket, cb);
-
-       if (ret < 0) {
-               DBG("nl_recvmsgs() ret: %d (%s)", ret, nl_geterror(-ret));
-               goto out;
+               if (ret < 0) {
+                       DBG("nl_recvmsgs() ret: %d (%s)", ret, nl_geterror(-ret));
+                       goto out;
+               }
        }
 
-       while (!results.done)
-               nl_recvmsgs(socket, cb);
+       while (!results.done) {
+               ret = nl_recvmsgs(socket, cb);
+               if (ret < 0 || err < 0) {
+                       DBG("scan failed");
+                       ret = -1;
+                       goto out;
+               }
+       }
 
        if (results.aborted) {
                DBG("scan aborted");
+               ret = -1;
                goto out;
        }