2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include "netsupplicant.h"
24 #include "wifi-bssid-scan.h"
26 #include "wifi-power.h"
27 #include "wifi-state.h"
28 #include "wifi-scan.h"
29 #include "wifi-background-scan.h"
31 #define NETCONFIG_SSID_LEN 32
32 #define NETCONFIG_BSSID_LEN 6
34 #define VCONF_WIFI_ALWAYS_ALLOW_SCANNING \
35 "file/private/wifi/always_allow_scanning"
38 unsigned char ssid[NETCONFIG_SSID_LEN + 1];
39 unsigned char bssid[NETCONFIG_BSSID_LEN + 1];
43 unsigned int frequency;
49 GSList *scan_info_list;
52 static GSList *g_bssid_scan_list = NULL;
54 static void __free_bssid_scan_data(gpointer data)
56 bssid_scan_data_s *scan_data = data;
58 g_slist_free_full(scan_data->scan_info_list, g_free);
59 g_free(scan_data->interface_name);
63 static bssid_scan_data_s *__create_bssid_scan_data(const char *interface_name)
65 bssid_scan_data_s *scan_data;
67 scan_data = g_try_new0(bssid_scan_data_s, 1);
68 if (scan_data == NULL)
71 scan_data->interface_name = g_strdup(interface_name);
73 g_bssid_scan_list = g_slist_append(g_bssid_scan_list, scan_data);
78 static bssid_scan_data_s *__get_bssid_scan_data(const char *interface_name)
81 bssid_scan_data_s *scan_data = NULL;
83 for (list = g_bssid_scan_list; list; list = list->next) {
84 scan_data = list->data;
85 if (g_strcmp0(scan_data->interface_name, interface_name) == 0)
89 scan_data = __create_bssid_scan_data(interface_name);
93 static void __update_bssid_scan_info_count(const char *interface_name,
96 bssid_scan_data_s *scan_data;
98 scan_data = __get_bssid_scan_data(interface_name);
99 if (scan_data == NULL)
103 scan_data->scan_info_count--;
105 scan_data->scan_info_count++;
108 static int __get_bssid_scan_info_count(const char *interface_name)
110 bssid_scan_data_s *scan_data;
112 scan_data = __get_bssid_scan_data(interface_name);
113 if (scan_data == NULL)
116 return scan_data->scan_info_count;
119 static void __append_bssid_scan_info(const char *interface_name,
120 bssid_scan_info_s *scan_info)
122 bssid_scan_data_s *scan_data;
124 scan_data = __get_bssid_scan_data(interface_name);
125 if (scan_data == NULL)
128 scan_data->scan_info_list = g_slist_append(scan_data->scan_info_list, scan_info);
131 static void __destroy_bssid_scan_data(const char *interface_name)
133 bssid_scan_data_s *scan_data;
135 scan_data = __get_bssid_scan_data(interface_name);
136 if (scan_data == NULL)
139 g_bssid_scan_list = g_slist_remove(g_bssid_scan_list, scan_data);
140 __free_bssid_scan_data(scan_data);
143 static void __netconfig_wifi_bssid_notify_scan_done(const char *interface_name)
145 GVariantBuilder *builder = NULL;
146 GVariantBuilder *builder1 = NULL;
148 const char *prop_ssid = "ssid";
149 const char *prop_bssid = "bssid";
150 const char *prop_rssi = "rssi";
151 const char *prop_mode = "mode";
152 const char *prop_freq = "frequency";
153 bssid_scan_data_s *scan_data = NULL;
155 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
157 scan_data = __get_bssid_scan_data(interface_name);
158 if (scan_data == NULL)
161 for (list = scan_data->scan_info_list; list != NULL; list = list->next) {
162 bssid_scan_info_s *bss_info = (bssid_scan_info_s *)list->data;
165 gchar bssid_buff[18] = { 0, };
166 gchar *bssid_str = bssid_buff;
167 unsigned char *ssid = (unsigned char *)bss_info->ssid;
168 int ssid_len = (int)bss_info->ssid_len;
169 int rssi = (int)bss_info->rssi;
170 int mode = (int)bss_info->mode;
171 guint32 frequency = (guint32)bss_info->frequency;
173 g_snprintf(bssid_buff, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
174 bss_info->bssid[0], bss_info->bssid[1], bss_info->bssid[2],
175 bss_info->bssid[3], bss_info->bssid[4], bss_info->bssid[5]);
177 SECURE_LOGD("BSS found; SSID %s, BSSID %s, RSSI %d MODE %d, Frequency %d",
178 ssid, bssid_str, rssi, mode, frequency);
180 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
181 for (i = 0; i < ssid_len; i++)
182 g_variant_builder_add(builder1, "y", ssid[i]);
183 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_builder_end(builder1));
184 g_variant_builder_unref(builder1);
186 g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid_str));
187 g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(rssi));
188 g_variant_builder_add(builder, "{sv}", prop_mode, g_variant_new_int32(mode));
189 g_variant_builder_add(builder, "{sv}", prop_freq, g_variant_new_uint32(frequency));
194 wifi_emit_bssid_scan_completed((Wifi *)get_wifi_object(),
195 interface_name, g_variant_builder_end(builder));
196 g_variant_builder_unref(builder);
198 __destroy_bssid_scan_data(interface_name);
200 INFO("BSSIDScanCompleted");
205 static void __netconfig_wifi_bssid_get_bss_info_result(
206 GObject *source_object, GAsyncResult *res, gpointer user_data)
208 GVariant *reply = NULL;
212 bssid_scan_info_s *bss_info;
213 GDBusConnection *conn = NULL;
214 GError *error = NULL;
215 char *interface_name = user_data;
217 conn = G_DBUS_CONNECTION(source_object);
218 reply = g_dbus_connection_call_finish(conn, res, &error);
221 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
226 bss_info = g_try_new0(bssid_scan_info_s, 1);
227 if (bss_info == NULL)
230 g_variant_get(reply, "(a{sv})", &iter);
231 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
233 if (g_strcmp0(key, "BSSID") == 0) {
237 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
238 if (bssid != NULL && bssid_len == NETCONFIG_BSSID_LEN)
239 memcpy(bss_info->bssid, bssid, bssid_len);
240 } else if (g_strcmp0(key, "SSID") == 0) {
244 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
245 if (ssid != NULL && ssid_len > 0 && ssid_len <= NETCONFIG_SSID_LEN) {
246 memcpy(bss_info->ssid, ssid, ssid_len);
247 bss_info->ssid_len = ssid_len;
249 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
250 bss_info->ssid_len = 0;
252 } else if (g_strcmp0(key, "Mode") == 0) {
255 g_variant_get(value, "s", &mode);
259 if (g_strcmp0(mode, "infrastructure") == 0)
261 else if (g_strcmp0(mode, "ad-hoc") == 0)
267 } else if (g_strcmp0(key, "Signal") == 0) {
270 signal = g_variant_get_int16(value);
271 bss_info->rssi = signal;
272 } else if (g_strcmp0(key, "Frequency") == 0) {
275 frequency = g_variant_get_uint16(value);
276 bss_info->frequency = (unsigned int)frequency;
281 if (bss_info->ssid[0] == '\0')
284 __append_bssid_scan_info(interface_name, bss_info);
286 g_variant_iter_free(iter);
289 g_variant_unref(reply);
291 netconfig_gdbus_pending_call_unref();
293 __update_bssid_scan_info_count(interface_name, 0);
294 if (__get_bssid_scan_info_count(interface_name) <= 0) {
295 __netconfig_wifi_bssid_notify_scan_done(interface_name);
297 if (netconfig_wifi_bssidscan_get_aborted(interface_name) == FALSE)
298 wifi_power_driver_and_supplicant(interface_name, FALSE);
301 g_free(interface_name);
304 static void __netconfig_wifi_bssid_get_bss_info(const char *interface_name,
307 gboolean reply = FALSE;
308 GVariant *param = NULL;
310 param = g_variant_new("(s)", SUPPLICANT_IFACE_BSS);
312 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
313 path, DBUS_INTERFACE_PROPERTIES, "GetAll", param,
314 __netconfig_wifi_bssid_get_bss_info_result,
315 g_strdup(interface_name));
317 ERR("Fail to invoke_dbus_method_nonblock GetAll");
322 static void __netconfig_wifi_bssid_get_bss_result(GObject *source_object,
323 GAsyncResult *res, gpointer user_data)
325 GVariant *reply = NULL;
326 GVariant *value = NULL;
327 GVariantIter *iter = NULL;
328 GDBusConnection *conn = NULL;
330 gboolean counter_flag = FALSE;
331 GError *error = NULL;
332 char *interface_name = user_data;
334 conn = G_DBUS_CONNECTION(source_object);
335 reply = g_dbus_connection_call_finish(conn, res, &error);
337 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
342 g_variant_get(reply, "(v)", &value);
343 if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
344 g_variant_get(value, "ao", &iter);
345 while (g_variant_iter_next(iter, "o", &path)) {
346 if (path != NULL && g_strcmp0(path, "/") != 0) {
347 __update_bssid_scan_info_count(interface_name, 1);
348 __netconfig_wifi_bssid_get_bss_info(interface_name, path);
359 g_variant_iter_free(iter);
362 g_variant_unref(value);
366 g_variant_unref(reply);
368 netconfig_gdbus_pending_call_unref();
370 /* Send BssidScanCompleted signal even when the BSS count is 0 */
371 if (__get_bssid_scan_info_count(interface_name) <= 0 && counter_flag == FALSE) {
372 __netconfig_wifi_bssid_notify_scan_done(interface_name);
374 if (netconfig_wifi_bssidscan_get_aborted(interface_name) == FALSE)
375 wifi_power_driver_and_supplicant(interface_name, FALSE);
378 g_free(interface_name);
381 static int _netconfig_wifi_bssid_get_bss(const char *interface_name)
383 gboolean reply = FALSE;
384 char *if_path = NULL;
385 GVariant *params = NULL;
387 if_path = netconfig_wifi_get_supplicant_interface_path(interface_name);
388 if (if_path == NULL) {
389 DBG("Fail to get wpa_supplicant DBus path");
393 params = g_variant_new("(ss)", SUPPLICANT_IFACE_INTERFACE, "BSSs");
395 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
396 if_path, DBUS_INTERFACE_PROPERTIES, "Get", params,
397 __netconfig_wifi_bssid_get_bss_result,
398 g_strdup(interface_name));
402 ERR("Fail to method: Get");
410 void netconfig_wifi_bssid_signal_scandone(const char *interface_name)
412 _netconfig_wifi_bssid_get_bss(interface_name);
414 netconfig_wifi_bssidscan_set_scanning(interface_name, FALSE);
415 netconfig_wifi_bssidscan_set_mode(interface_name, FALSE);
418 void netconfig_wifi_bssid_signal_scanaborted(const char *interface_name)
420 netconfig_wifi_bssidscan_set_aborted(interface_name, TRUE);
421 _netconfig_wifi_bssid_get_bss(interface_name);
423 netconfig_wifi_bssidscan_set_scanning(interface_name, FALSE);
424 netconfig_wifi_bssidscan_set_mode(interface_name, FALSE);
427 static void __netconfig_wifi_bssid_scan_request_reply(GObject *source_object,
428 GAsyncResult *res, gpointer user_data)
431 GDBusConnection *conn = NULL;
432 GError *error = NULL;
434 conn = G_DBUS_CONNECTION(source_object);
435 message = g_dbus_connection_call_finish(conn, res, &error);
437 if (message == NULL) {
439 ERR("Fail to request status [%d: %s]", error->code, error->message);
442 ERR("Fail to request bssid scan");
445 DBG("Successfully requested bssid scan");
446 g_variant_unref(message);
449 netconfig_gdbus_pending_call_unref();
452 static int __netconfig_wifi_bssid_request_scan(const char *interface_name, char *if_path)
454 GVariant *message = NULL;
455 GVariantBuilder *builder = NULL;
456 const char *key1 = "Type";
457 const char *val1 = "passive";
458 gboolean is_free_required = FALSE;
459 gboolean reply = FALSE;
461 if (if_path == NULL) {
462 if_path = netconfig_wifi_get_supplicant_interface_path(interface_name);
463 is_free_required = TRUE;
466 if (if_path == NULL) {
467 DBG("Fail to get wpa_supplicant DBus path");
471 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
472 g_variant_builder_add(builder, "{sv}", key1, g_variant_new_string(val1));
473 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
474 g_variant_builder_unref(builder);
476 DBG("[net-config]: TizenMW-->WPAS: .Interface.Scan");
477 reply = netconfig_supplicant_invoke_dbus_method_nonblock(
480 SUPPLICANT_INTERFACE ".Interface",
483 (GAsyncReadyCallback) __netconfig_wifi_bssid_scan_request_reply,
491 netconfig_wifi_bssidscan_set_scanning(interface_name, TRUE);
494 if (is_free_required)
497 /* Clear bss_info_list for the next scan result */
498 __destroy_bssid_scan_data(interface_name);
500 netconfig_wifi_bssidscan_set_aborted(interface_name, FALSE);
505 static void __netconfig_wifi_interface_create_result(
506 GObject *source_object, GAsyncResult *res, gpointer user_data)
508 GVariant *message = NULL;
510 GDBusConnection *conn = NULL;
511 GError *error = NULL;
512 char *interface_name = user_data;
514 conn = G_DBUS_CONNECTION(source_object);
516 message = g_dbus_connection_call_finish(conn, res, &error);
518 g_variant_get(message, "(o)", &path);
521 __netconfig_wifi_bssid_request_scan(interface_name, path);
524 } else if (NULL != strstr(error->message, ".InterfaceExists")) {
525 INFO("Error Message %s %s", error->message, path);
526 g_variant_get(message, "(o)", &path);
528 __netconfig_wifi_bssid_request_scan(interface_name, path);
531 __netconfig_wifi_bssid_request_scan(interface_name, NULL);
535 ERR("Failed to create interface, Error: %d[%s]", error->code, error->message);
536 netconfig_wifi_bssidscan_set_mode(interface_name, FALSE);
537 wifi_power_driver_and_supplicant(interface_name, FALSE);
541 g_variant_unref(message);
542 g_free(interface_name);
543 netconfig_gdbus_pending_call_unref();
546 static int __netconfig_wifi_bssid_create_interface(const char *interface_name)
548 GVariant *message = NULL;
549 GVariantBuilder *builder = NULL;
550 const char *key = "Ifname";
551 gboolean reply = FALSE;
553 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
554 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(interface_name));
555 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
556 g_variant_builder_unref(builder);
558 DBG("[net-config]: TizenMW-->WPAS: CreateInterface");
559 reply = netconfig_supplicant_invoke_dbus_method_nonblock(
562 SUPPLICANT_INTERFACE,
565 (GAsyncReadyCallback) __netconfig_wifi_interface_create_result,
566 g_strdup(interface_name));
569 ERR("Fail to CreateInterface");
574 static int __netconfig_wifi_bssid_scan(const char *interface_name)
577 wifi_tech_state_e wifi_tech_state;
579 if (netconfig_wifi_bssidscan_get_scanning(interface_name) == TRUE)
582 wifi_tech_state = wifi_state_get_technology_state(interface_name);
583 if (wifi_tech_state <= NETCONFIG_WIFI_TECH_OFF)
584 err = wifi_power_driver_and_supplicant(interface_name, TRUE);
586 if (err < 0 && err != -EALREADY)
589 netconfig_wifi_bssidscan_set_scanning(interface_name, TRUE);
591 DBG("BSSID scan requested");
592 if (wifi_tech_state >= NETCONFIG_WIFI_TECH_POWERED) {
593 if (netconfig_wifi_scan_get_scanning(interface_name) == TRUE)
596 netconfig_wifi_bgscan_start(interface_name, TRUE);
598 if (wifi_tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
599 __netconfig_wifi_bssid_request_scan(interface_name, NULL);
601 err = __netconfig_wifi_bssid_create_interface(interface_name);
607 gboolean handle_request_bssid_scan(Wifi *wifi, GDBusMethodInvocation *context,
610 int err, enabled = 0;
611 wifi_tech_state_e tech_state;
613 g_return_val_if_fail(wifi != NULL, TRUE);
615 if (netconfig_is_wifi_tethering_on() == TRUE) {
616 ERR("Wi-Fi Tethering is enabled");
617 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "TetheringEnabled");
621 #if !defined TIZEN_WEARABLE
622 if (netconfig_wifi_bgscan_is_paused(ifname)) {
623 ERR("Scan is paused");
624 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "ScanPaused");
629 tech_state = wifi_state_get_technology_state(ifname);
630 if (tech_state <= NETCONFIG_WIFI_TECH_OFF) {
631 #if !defined TIZEN_WEARABLE
638 netconfig_error_permission_denied(context);
643 netconfig_wifi_bssidscan_set_mode(ifname, TRUE);
645 err = __netconfig_wifi_bssid_scan(ifname);
647 if (err == -EINPROGRESS)
648 netconfig_error_inprogress(context);
650 netconfig_error_wifi_driver_failed(context);
655 wifi_complete_request_bssid_scan(wifi, context);
659 gboolean handle_get_bssid_list(Wifi *wifi, GDBusMethodInvocation *context,
662 __create_bssid_scan_data(ifname);
663 _netconfig_wifi_bssid_get_bss(ifname);
665 wifi_complete_get_bssid_list(wifi, context);