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.
29 #include "wifi-power.h"
30 #include "wifi-state.h"
31 #include "netsupplicant.h"
32 #include "wifi-background-scan.h"
34 #define NETCONFIG_SSID_LEN 32
35 #define NETCONFIG_BSSID_LEN 6
36 #define NETCONFIG_WPS_DBUS_REPLY_TIMEOUT (10 * 1000)
38 #define VCONF_WIFI_ALWAYS_ALLOW_SCANNING \
39 "file/private/wifi/always_allow_scanning"
41 static gboolean netconfig_is_wps_enabled = FALSE;
42 static gboolean netconfig_is_device_scanning = FALSE;
43 static gboolean netconfig_is_wps_scan_aborted = FALSE;
44 static int wps_bss_list_count = 0;
46 struct wps_bss_info_t {
47 unsigned char ssid[NETCONFIG_SSID_LEN + 1];
48 unsigned char bssid[NETCONFIG_BSSID_LEN + 1];
54 static GSList *wps_bss_info_list = NULL;
56 static void __netconfig_wps_set_mode(gboolean enable)
58 if (netconfig_is_wps_enabled == enable)
61 netconfig_is_wps_enabled = enable;
64 gboolean netconfig_wifi_is_wps_enabled(void)
66 return netconfig_is_wps_enabled;
69 static void __netconfig_wifi_wps_notify_scan_done(void)
71 GVariantBuilder *builder = NULL;
72 GVariantBuilder *builder1 = NULL;
74 const char *prop_ssid = "ssid";
75 const char *prop_bssid = "bssid";
76 const char *prop_rssi = "rssi";
77 const char *prop_mode = "mode";
79 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
80 for (list = wps_bss_info_list; list != NULL; list = list->next) {
81 struct wps_bss_info_t *bss_info = (struct wps_bss_info_t *)list->data;
84 gchar bssid_buff[18] = { 0, };
85 gchar *bssid_str = bssid_buff;
86 unsigned char *ssid = (unsigned char *)bss_info->ssid;
87 int ssid_len = (int)bss_info->ssid_len;
88 int rssi = (int)bss_info->rssi;
89 int mode = (int)bss_info->mode;
91 g_snprintf(bssid_buff, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
92 bss_info->bssid[0], bss_info->bssid[1], bss_info->bssid[2],
93 bss_info->bssid[3], bss_info->bssid[4], bss_info->bssid[5]);
95 DBG("BSS found; SSID %s, BSSID %s, RSSI %d MODE %d", ssid, bssid_str, rssi, mode);
97 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
98 for (i = 0; i < ssid_len; i++)
99 g_variant_builder_add(builder1, "y", ssid[i]);
100 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_builder_end(builder1));
101 g_variant_builder_unref(builder1);
103 g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid_str));
104 g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(rssi));
105 g_variant_builder_add(builder, "{sv}", prop_mode, g_variant_new_int32(mode));
109 wifi_emit_wps_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
110 g_variant_builder_unref(builder);
112 if (wps_bss_info_list != NULL)
113 g_slist_free_full(wps_bss_info_list, g_free);
115 wps_bss_info_list = NULL;
116 wps_bss_list_count = 0;
117 INFO("WpsScanCompleted");
122 static void __netconfig_wifi_wps_get_bss_info_result(
123 GObject *source_object, GAsyncResult *res, gpointer user_data)
125 GVariant *reply = NULL;
129 struct wps_bss_info_t *bss_info;
130 GDBusConnection *conn = NULL;
131 GError *error = NULL;
133 conn = G_DBUS_CONNECTION(source_object);
134 reply = g_dbus_connection_call_finish(conn, res, &error);
137 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
142 bss_info = g_try_new0(struct wps_bss_info_t, 1);
143 if (bss_info == NULL)
146 g_variant_get(reply, "(a{sv})", &iter);
147 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
149 if (g_strcmp0(key, "BSSID") == 0) {
153 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
154 if (bssid_len == NETCONFIG_BSSID_LEN)
155 memcpy(bss_info->bssid, bssid, bssid_len);
156 } else if (g_strcmp0(key, "SSID") == 0) {
160 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
161 if (ssid != NULL && ssid_len > 0 && ssid_len <= NETCONFIG_SSID_LEN) {
162 memcpy(bss_info->ssid, ssid, ssid_len);
163 bss_info->ssid_len = ssid_len;
165 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
166 bss_info->ssid_len = 0;
168 } else if (g_strcmp0(key, "Mode") == 0) {
171 g_variant_get(value, "s", &mode);
175 if (g_strcmp0(mode, "infrastructure") == 0)
177 else if (g_strcmp0(mode, "ad-hoc") == 0)
183 } else if (g_strcmp0(key, "Signal") == 0) {
186 signal = g_variant_get_int16(value);
187 bss_info->rssi = signal;
192 if (bss_info->ssid[0] == '\0')
195 wps_bss_info_list = g_slist_append(wps_bss_info_list, bss_info);
197 g_variant_iter_free(iter);
200 g_variant_unref(reply);
202 netconfig_gdbus_pending_call_unref();
204 wps_bss_list_count--;
205 if (wps_bss_list_count <= 0) {
206 __netconfig_wifi_wps_notify_scan_done();
208 if (netconfig_is_wps_scan_aborted == FALSE)
209 wifi_power_driver_and_supplicant(FALSE);
213 static void __netconfig_wifi_wps_get_bss_info(const char *path, int index)
215 gboolean reply = FALSE;
216 GVariant *param = NULL;
218 param = g_variant_new("(s)", SUPPLICANT_IFACE_BSS);
220 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
221 path, DBUS_INTERFACE_PROPERTIES,
222 "GetAll", param, __netconfig_wifi_wps_get_bss_info_result);
224 ERR("Fail to invoke_dbus_method_nonblock GetAll");
229 static void __netconfig_wifi_wps_get_bsss_result(GObject *source_object,
230 GAsyncResult *res, gpointer user_data)
232 GVariant *reply = NULL;
233 GVariant *value = NULL;
234 GVariantIter *iter = NULL;
235 GDBusConnection *conn = NULL;
237 gboolean counter_flag = FALSE;
238 GError *error = NULL;
240 conn = G_DBUS_CONNECTION(source_object);
241 reply = g_dbus_connection_call_finish(conn, res, &error);
243 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
248 g_variant_get(reply, "(v)", &value);
249 if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
250 g_variant_get(value, "ao", &iter);
251 while (g_variant_iter_next(iter, "o", &path)) {
252 if (path != NULL && g_strcmp0(path, "/") != 0) {
253 __netconfig_wifi_wps_get_bss_info(path, ++wps_bss_list_count);
264 g_variant_iter_free(iter);
267 g_variant_unref(value);
271 g_variant_unref(reply);
273 netconfig_gdbus_pending_call_unref();
275 /* Send WpsScanCompleted signal even when the BSS count is 0 */
276 if (wps_bss_list_count <= 0 && counter_flag == FALSE) {
277 __netconfig_wifi_wps_notify_scan_done();
279 if (netconfig_is_wps_scan_aborted == FALSE)
280 wifi_power_driver_and_supplicant(FALSE);
284 static int _netconfig_wifi_wps_get_bsss(void)
286 gboolean reply = FALSE;
287 const char *if_path = NULL;
288 GVariant *params = NULL;
290 if_path = netconfig_wifi_get_supplicant_interface();
291 if (if_path == NULL) {
292 DBG("Fail to get wpa_supplicant DBus path");
296 params = g_variant_new("(ss)", SUPPLICANT_IFACE_INTERFACE, "BSSs");
298 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
299 if_path, DBUS_INTERFACE_PROPERTIES,
300 "Get", params, __netconfig_wifi_wps_get_bsss_result);
302 ERR("Fail to method: Get");
310 void netconfig_wifi_wps_signal_scandone(void)
312 wps_bss_list_count = 0;
313 _netconfig_wifi_wps_get_bsss();
315 netconfig_is_device_scanning = FALSE;
317 __netconfig_wps_set_mode(FALSE);
320 void netconfig_wifi_wps_signal_scanaborted(void)
322 wps_bss_list_count = 0;
323 netconfig_is_wps_scan_aborted = TRUE;
324 _netconfig_wifi_wps_get_bsss();
326 netconfig_is_device_scanning = FALSE;
328 __netconfig_wps_set_mode(FALSE);
331 static int __netconfig_wifi_wps_request_scan(const char *if_path)
333 GDBusConnection *connection = NULL;
334 GVariant *message = NULL;
335 GVariantBuilder *builder = NULL;
336 const char *key1 = "Type";
337 const char *val1 = "passive";
340 if_path = netconfig_wifi_get_supplicant_interface();
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_WPS_DBUS_REPLY_TIMEOUT,
367 netdbus_get_cancellable(),
371 netconfig_is_device_scanning = TRUE;
373 g_variant_unref(message);
374 /* Clear bss_info_list for the next scan result */
375 if (wps_bss_info_list) {
376 g_slist_free_full(wps_bss_info_list, g_free);
377 wps_bss_info_list = NULL;
380 netconfig_is_wps_scan_aborted = FALSE;
385 static void __netconfig_wifi_interface_create_result(
386 GObject *source_object, GAsyncResult *res, gpointer user_data)
390 GDBusConnection *conn = NULL;
391 GError *error = NULL;
393 conn = G_DBUS_CONNECTION(source_object);
395 message = g_dbus_connection_call_finish(conn, res, &error);
397 g_variant_get(message, "(o)", &path);
400 __netconfig_wifi_wps_request_scan(path);
404 else if (NULL != strstr(error->message, ".InterfaceExists")) {
405 INFO("Error Message %s %s", error->message, path);
406 g_variant_get(message, "(o)", &path);
408 __netconfig_wifi_wps_request_scan(path);
412 __netconfig_wifi_wps_request_scan(NULL);
414 ERR("Failed to create interface, Error: %d[%s]", error->code, error->message);
415 __netconfig_wps_set_mode(FALSE);
416 wifi_power_driver_and_supplicant(FALSE);
419 g_variant_unref(message);
422 static int __netconfig_wifi_wps_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_WPS_DBUS_REPLY_TIMEOUT,
449 netdbus_get_cancellable(),
450 (GAsyncReadyCallback) __netconfig_wifi_interface_create_result,
453 g_variant_unref(message);
458 static int __netconfig_wifi_wps_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("WPS 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_wps_request_scan(NULL);
485 err = __netconfig_wifi_wps_create_interface();
491 gboolean handle_request_wps_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, FALSE);
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
515 vconf_get_int(VCONF_WIFI_ALWAYS_ALLOW_SCANNING, &enabled);
521 netconfig_error_permission_denied(context);
526 __netconfig_wps_set_mode(TRUE);
528 err = __netconfig_wifi_wps_scan();
530 if (err == -EINPROGRESS)
531 netconfig_error_inprogress(context);
533 netconfig_error_wifi_driver_failed(context);
538 wifi_complete_request_wps_scan(wifi, context);
543 static void __interface_wps_cancel_result(GObject *source_object,
544 GAsyncResult *res, gpointer user_data)
547 GDBusConnection *conn = NULL;
548 GError *error = NULL;
550 conn = G_DBUS_CONNECTION(source_object);
551 reply = g_dbus_connection_call_finish(conn, res, &error);
555 ERR("Fail to request status [%d: %s]",
556 error->code, error->message);
559 ERR("Fail torequest status");
562 DBG("Successfully M/W--->WPAS: Interface.WPS.Cancel Method");
565 g_variant_unref(reply);
566 netconfig_gdbus_pending_call_unref();
569 static gboolean __netconfig_wifi_invoke_wps_cancel()
571 gboolean reply = FALSE;
572 const char *if_path = NULL;
574 if_path = netconfig_wifi_get_supplicant_interface();
575 if (if_path == NULL) {
576 DBG("Fail to get wpa_supplicant DBus path");
580 DBG("M/W--->WPAS: Interface.WPS.Cancel Method");
582 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
583 if_path, SUPPLICANT_IFACE_WPS,
584 "Cancel", NULL, __interface_wps_cancel_result);
587 ERR("M/W--->WPAS: Interface.WPS.Cancel Method Failed");
593 gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context)
596 DBG("Received WPS PBC Cancel Request");
597 g_return_val_if_fail(wifi != NULL, FALSE);
598 return __netconfig_wifi_invoke_wps_cancel();
600 /*Not supported for mobile and Wearable profile*/