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-background-scan.h"
30 #define NETCONFIG_SSID_LEN 32
31 #define NETCONFIG_BSSID_LEN 6
33 #define VCONF_WIFI_ALWAYS_ALLOW_SCANNING \
34 "file/private/wifi/always_allow_scanning"
36 static gboolean netconfig_is_bssid_scan_started = FALSE;
37 static gboolean netconfig_is_device_scanning = FALSE;
38 static gboolean netconfig_is_bssid_scan_aborted = FALSE;
39 static int bssid_list_count = 0;
40 static GSList *bssid_info_list = NULL;
42 struct bssid_scan_info_t {
43 unsigned char ssid[NETCONFIG_SSID_LEN + 1];
44 unsigned char bssid[NETCONFIG_BSSID_LEN + 1];
50 gboolean netconfig_wifi_is_bssid_scan_started(void)
52 return netconfig_is_bssid_scan_started;
55 static void __netconfig_wifi_bssid_notify_scan_done(void)
57 GVariantBuilder *builder = NULL;
58 GVariantBuilder *builder1 = NULL;
60 const char *prop_ssid = "ssid";
61 const char *prop_bssid = "bssid";
62 const char *prop_rssi = "rssi";
63 const char *prop_mode = "mode";
65 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
66 for (list = bssid_info_list; list != NULL; list = list->next) {
67 struct bssid_scan_info_t *bss_info = (struct bssid_scan_info_t *)list->data;
70 gchar bssid_buff[18] = { 0, };
71 gchar *bssid_str = bssid_buff;
72 unsigned char *ssid = (unsigned char *)bss_info->ssid;
73 int ssid_len = (int)bss_info->ssid_len;
74 int rssi = (int)bss_info->rssi;
75 int mode = (int)bss_info->mode;
77 g_snprintf(bssid_buff, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
78 bss_info->bssid[0], bss_info->bssid[1], bss_info->bssid[2],
79 bss_info->bssid[3], bss_info->bssid[4], bss_info->bssid[5]);
81 DBG("BSS found; SSID %s, BSSID %s, RSSI %d MODE %d", ssid, bssid_str, rssi, mode);
83 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
84 for (i = 0; i < ssid_len; i++)
85 g_variant_builder_add(builder1, "y", ssid[i]);
86 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_builder_end(builder1));
87 g_variant_builder_unref(builder1);
89 g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid_str));
90 g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(rssi));
91 g_variant_builder_add(builder, "{sv}", prop_mode, g_variant_new_int32(mode));
95 wifi_emit_bssid_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
96 g_variant_builder_unref(builder);
98 if (bssid_info_list != NULL)
99 g_slist_free_full(bssid_info_list, g_free);
101 bssid_info_list = NULL;
102 bssid_list_count = 0;
103 INFO("BSSIDScanCompleted");
108 static void __netconfig_wifi_bssid_get_bss_info_result(
109 GObject *source_object, GAsyncResult *res, gpointer user_data)
111 GVariant *reply = NULL;
115 struct bssid_scan_info_t *bss_info;
116 GDBusConnection *conn = NULL;
117 GError *error = NULL;
119 conn = G_DBUS_CONNECTION(source_object);
120 reply = g_dbus_connection_call_finish(conn, res, &error);
123 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
128 bss_info = g_try_new0(struct bssid_scan_info_t, 1);
129 if (bss_info == NULL)
132 g_variant_get(reply, "(a{sv})", &iter);
133 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
135 if (g_strcmp0(key, "BSSID") == 0) {
139 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
140 if (bssid_len == NETCONFIG_BSSID_LEN)
141 memcpy(bss_info->bssid, bssid, bssid_len);
142 } else if (g_strcmp0(key, "SSID") == 0) {
146 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
147 if (ssid != NULL && ssid_len > 0 && ssid_len <= NETCONFIG_SSID_LEN) {
148 memcpy(bss_info->ssid, ssid, ssid_len);
149 bss_info->ssid_len = ssid_len;
151 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
152 bss_info->ssid_len = 0;
154 } else if (g_strcmp0(key, "Mode") == 0) {
157 g_variant_get(value, "s", &mode);
161 if (g_strcmp0(mode, "infrastructure") == 0)
163 else if (g_strcmp0(mode, "ad-hoc") == 0)
169 } else if (g_strcmp0(key, "Signal") == 0) {
172 signal = g_variant_get_int16(value);
173 bss_info->rssi = signal;
178 if (bss_info->ssid[0] == '\0')
181 bssid_info_list = g_slist_append(bssid_info_list, bss_info);
183 g_variant_iter_free(iter);
186 g_variant_unref(reply);
188 netconfig_gdbus_pending_call_unref();
191 if (bssid_list_count <= 0) {
192 __netconfig_wifi_bssid_notify_scan_done();
194 if (netconfig_is_bssid_scan_aborted == FALSE)
195 wifi_power_driver_and_supplicant(FALSE);
199 static void __netconfig_wifi_bssid_get_bss_info(const char *path, int index)
201 gboolean reply = FALSE;
202 GVariant *param = NULL;
204 param = g_variant_new("(s)", SUPPLICANT_IFACE_BSS);
206 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
207 path, DBUS_INTERFACE_PROPERTIES,
208 "GetAll", param, __netconfig_wifi_bssid_get_bss_info_result);
210 ERR("Fail to invoke_dbus_method_nonblock GetAll");
215 static void __netconfig_wifi_bssid_get_bss_result(GObject *source_object,
216 GAsyncResult *res, gpointer user_data)
218 GVariant *reply = NULL;
219 GVariant *value = NULL;
220 GVariantIter *iter = NULL;
221 GDBusConnection *conn = NULL;
223 gboolean counter_flag = FALSE;
224 GError *error = NULL;
226 conn = G_DBUS_CONNECTION(source_object);
227 reply = g_dbus_connection_call_finish(conn, res, &error);
229 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
234 g_variant_get(reply, "(v)", &value);
235 if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
236 g_variant_get(value, "ao", &iter);
237 while (g_variant_iter_next(iter, "o", &path)) {
238 if (path != NULL && g_strcmp0(path, "/") != 0) {
239 __netconfig_wifi_bssid_get_bss_info(path, ++bssid_list_count);
250 g_variant_iter_free(iter);
253 g_variant_unref(value);
257 g_variant_unref(reply);
259 netconfig_gdbus_pending_call_unref();
261 /* Send BssidScanCompleted signal even when the BSS count is 0 */
262 if (bssid_list_count <= 0 && counter_flag == FALSE) {
263 __netconfig_wifi_bssid_notify_scan_done();
265 if (netconfig_is_bssid_scan_aborted == FALSE)
266 wifi_power_driver_and_supplicant(FALSE);
270 static int _netconfig_wifi_bssid_get_bss(void)
272 gboolean reply = FALSE;
273 char *if_path = NULL;
274 GVariant *params = NULL;
276 if_path = netconfig_wifi_get_supplicant_interface();
277 if (if_path == NULL) {
278 DBG("Fail to get wpa_supplicant DBus path");
282 params = g_variant_new("(ss)", SUPPLICANT_IFACE_INTERFACE, "BSSs");
284 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
285 if_path, DBUS_INTERFACE_PROPERTIES,
286 "Get", params, __netconfig_wifi_bssid_get_bss_result);
290 ERR("Fail to method: Get");
299 static void __netconfig_set_bssid_scan_mode(gboolean enable)
301 if (netconfig_is_bssid_scan_started == enable)
304 netconfig_is_bssid_scan_started = enable;
307 void netconfig_wifi_bssid_signal_scandone(void)
309 bssid_list_count = 0;
310 _netconfig_wifi_bssid_get_bss();
312 netconfig_is_device_scanning = FALSE;
314 __netconfig_set_bssid_scan_mode(FALSE);
317 void netconfig_wifi_bssid_signal_scanaborted(void)
319 bssid_list_count = 0;
320 netconfig_is_bssid_scan_aborted = TRUE;
321 _netconfig_wifi_bssid_get_bss();
323 netconfig_is_device_scanning = FALSE;
325 __netconfig_set_bssid_scan_mode(FALSE);
328 static int __netconfig_wifi_bssid_request_scan(char *if_path)
330 GDBusConnection *connection = NULL;
331 GVariant *message = NULL;
332 GVariantBuilder *builder = NULL;
333 const char *key1 = "Type";
334 const char *val1 = "passive";
335 gboolean is_free_required = FALSE;
337 if (if_path == NULL) {
338 if_path = netconfig_wifi_get_supplicant_interface();
339 is_free_required = TRUE;
342 if (if_path == NULL) {
343 DBG("Fail to get wpa_supplicant DBus path");
347 connection = netdbus_get_connection();
348 if (connection == NULL) {
349 ERR("Failed to get GDBusconnection");
353 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
354 g_variant_builder_add(builder, "{sv}", key1, g_variant_new_string(val1));
355 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
356 g_variant_builder_unref(builder);
358 g_dbus_connection_call(connection,
361 SUPPLICANT_INTERFACE ".Interface",
365 G_DBUS_CALL_FLAGS_NONE,
366 NETCONFIG_DBUS_REPLY_TIMEOUT,
367 netdbus_get_cancellable(),
371 netconfig_is_device_scanning = TRUE;
373 if (is_free_required)
375 g_variant_unref(message);
376 /* Clear bss_info_list for the next scan result */
377 if (bssid_info_list) {
378 g_slist_free_full(bssid_info_list, g_free);
379 bssid_info_list = NULL;
382 netconfig_is_bssid_scan_aborted = FALSE;
387 static void __netconfig_wifi_interface_create_result(
388 GObject *source_object, GAsyncResult *res, gpointer user_data)
392 GDBusConnection *conn = NULL;
393 GError *error = NULL;
395 conn = G_DBUS_CONNECTION(source_object);
397 message = g_dbus_connection_call_finish(conn, res, &error);
399 g_variant_get(message, "(o)", &path);
402 __netconfig_wifi_bssid_request_scan(path);
405 } else if (NULL != strstr(error->message, ".InterfaceExists")) {
406 INFO("Error Message %s %s", error->message, path);
407 g_variant_get(message, "(o)", &path);
409 __netconfig_wifi_bssid_request_scan(path);
412 __netconfig_wifi_bssid_request_scan(NULL);
414 ERR("Failed to create interface, Error: %d[%s]", error->code, error->message);
415 __netconfig_set_bssid_scan_mode(FALSE);
416 wifi_power_driver_and_supplicant(FALSE);
419 g_variant_unref(message);
422 static int __netconfig_wifi_bssid_create_interface(void)
424 GDBusConnection *connection = NULL;
425 GVariant *message = NULL;
426 GVariantBuilder *builder = NULL;
427 const char *key = "Ifname";
428 const char *val = WIFI_IFNAME;
430 connection = netdbus_get_connection();
431 if (connection == NULL) {
432 DBG("Failed to get GDBusconnection");
436 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
437 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(val));
438 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
440 g_dbus_connection_call(connection,
443 SUPPLICANT_INTERFACE,
447 G_DBUS_CALL_FLAGS_NONE,
448 NETCONFIG_DBUS_REPLY_TIMEOUT,
449 netdbus_get_cancellable(),
450 (GAsyncReadyCallback) __netconfig_wifi_interface_create_result,
453 g_variant_unref(message);
458 static int __netconfig_wifi_bssid_scan(void)
461 wifi_tech_state_e wifi_tech_state;
463 if (netconfig_is_device_scanning == TRUE)
466 wifi_tech_state = wifi_state_get_technology_state();
467 if (wifi_tech_state <= NETCONFIG_WIFI_TECH_OFF)
468 err = wifi_power_driver_and_supplicant(TRUE);
470 if (err < 0 && err != -EALREADY)
473 netconfig_is_device_scanning = TRUE;
475 DBG("BSSID scan requested");
476 if (wifi_tech_state >= NETCONFIG_WIFI_TECH_POWERED) {
477 if (netconfig_wifi_get_scanning() == TRUE)
480 netconfig_wifi_bgscan_start(TRUE);
482 if (wifi_tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
483 __netconfig_wifi_bssid_request_scan(NULL);
485 err = __netconfig_wifi_bssid_create_interface();
491 gboolean handle_request_bssid_scan(Wifi *wifi, GDBusMethodInvocation *context)
493 int err, enabled = 0;
494 wifi_tech_state_e tech_state;
496 g_return_val_if_fail(wifi != NULL, TRUE);
498 if (netconfig_is_wifi_tethering_on() == TRUE) {
499 ERR("Wi-Fi Tethering is enabled");
500 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "TetheringEnabled");
504 #if !defined TIZEN_WEARABLE
505 if (netconfig_wifi_is_bgscan_paused()) {
506 ERR("Scan is paused");
507 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "ScanPaused");
512 tech_state = wifi_state_get_technology_state();
513 if (tech_state <= NETCONFIG_WIFI_TECH_OFF) {
514 #if !defined TIZEN_WEARABLE
521 netconfig_error_permission_denied(context);
526 __netconfig_set_bssid_scan_mode(TRUE);
528 err = __netconfig_wifi_bssid_scan();
530 if (err == -EINPROGRESS)
531 netconfig_error_inprogress(context);
533 netconfig_error_wifi_driver_failed(context);
538 wifi_complete_request_bssid_scan(wifi, context);
542 gboolean handle_get_bssid_list(Wifi *wifi, GDBusMethodInvocation *context)
544 _netconfig_wifi_bssid_get_bss();
545 wifi_complete_get_bssid_list(wifi, context);