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)//check this
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]);
101 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_builder_end(builder1));
102 g_variant_builder_unref(builder1);
104 g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid_str));
105 g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(rssi));
106 g_variant_builder_add(builder, "{sv}", prop_mode, g_variant_new_int32(mode));
110 wifi_emit_wps_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
111 g_variant_builder_unref(builder);
113 if (wps_bss_info_list != NULL) {
114 g_slist_free_full(wps_bss_info_list, g_free);
117 wps_bss_info_list = NULL;
118 wps_bss_list_count = 0;
119 INFO("WpsScanCompleted");
124 static void __netconfig_wifi_wps_get_bss_info_result(
125 GObject *source_object, GAsyncResult *res, gpointer user_data)
127 GVariant *reply = NULL;
131 struct wps_bss_info_t *bss_info;
132 GDBusConnection *conn = NULL;
133 GError *error = NULL;
135 conn = G_DBUS_CONNECTION (source_object);
136 reply = g_dbus_connection_call_finish(conn, res, &error);
139 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
144 bss_info = g_try_new0(struct wps_bss_info_t, 1);
145 if (bss_info == NULL)
148 g_variant_get(reply, "(a{sv})", &iter);
149 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
151 if (g_strcmp0(key, "BSSID") == 0) {
155 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
156 if (bssid_len == NETCONFIG_BSSID_LEN)
157 memcpy(bss_info->bssid, bssid, bssid_len);
158 } else if (g_strcmp0(key, "SSID") == 0) {
162 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
163 if (ssid != NULL && ssid_len > 0 && ssid_len <= NETCONFIG_SSID_LEN) {
164 memcpy(bss_info->ssid, ssid, ssid_len);
165 bss_info->ssid_len = ssid_len;
167 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
168 bss_info->ssid_len = 0;
170 } else if (g_strcmp0(key, "Mode") == 0) {
173 g_variant_get(value, "s", &mode);
177 if (g_strcmp0(mode, "infrastructure") == 0)
179 else if (g_strcmp0(mode, "ad-hoc") == 0)
185 } else if (g_strcmp0(key, "Signal") == 0) {
188 signal = g_variant_get_int16(value);
189 bss_info->rssi = signal;
194 if (bss_info->ssid[0] == '\0')
197 wps_bss_info_list = g_slist_append(wps_bss_info_list, bss_info);
199 g_variant_iter_free(iter);
202 g_variant_unref(reply);
204 netconfig_gdbus_pending_call_unref();
206 wps_bss_list_count--;
207 if (wps_bss_list_count <= 0) {
208 __netconfig_wifi_wps_notify_scan_done();
210 if (netconfig_is_wps_scan_aborted == FALSE)
211 wifi_power_driver_and_supplicant(FALSE);
215 static void __netconfig_wifi_wps_get_bss_info(const char *path, int index)
217 gboolean reply = FALSE;
218 GVariant *param = NULL;
220 param = g_variant_new("(s)", SUPPLICANT_IFACE_BSS);
222 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
223 path, DBUS_INTERFACE_PROPERTIES,
224 "GetAll", param, __netconfig_wifi_wps_get_bss_info_result);
226 ERR("Fail to invoke_dbus_method_nonblock GetAll");
231 static void __netconfig_wifi_wps_get_bsss_result(GObject *source_object,
232 GAsyncResult *res, gpointer user_data)
234 GVariant *reply = NULL;
235 GVariant *value = NULL;
236 GVariantIter *iter = NULL;
237 GDBusConnection *conn = NULL;
239 gboolean counter_flag = FALSE;
240 GError *error = NULL;
242 conn = G_DBUS_CONNECTION (source_object);
243 reply = g_dbus_connection_call_finish(conn, res, &error);
245 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
250 g_variant_get(reply, "(v)", &value);
251 if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
252 g_variant_get(value, "ao", &iter);
253 while (g_variant_iter_next(iter, "o", &path)) {
254 if (path != NULL && g_strcmp0(path, "/") != 0) {
255 __netconfig_wifi_wps_get_bss_info(path, ++wps_bss_list_count);
266 g_variant_iter_free(iter);
269 g_variant_unref(value);
273 g_variant_unref(reply);
275 netconfig_gdbus_pending_call_unref();
277 /* Send WpsScanCompleted signal even when the BSS count is 0 */
278 if (wps_bss_list_count <= 0 && counter_flag == FALSE) {
279 __netconfig_wifi_wps_notify_scan_done();
281 if (netconfig_is_wps_scan_aborted == FALSE)
282 wifi_power_driver_and_supplicant(FALSE);
286 static int _netconfig_wifi_wps_get_bsss(void)
288 gboolean reply = FALSE;
289 const char *if_path = NULL;
290 GVariant *params = NULL;
292 if_path = netconfig_wifi_get_supplicant_interface();
293 if (if_path == NULL) {
294 DBG("Fail to get wpa_supplicant DBus path");
298 params = g_variant_new("(ss)", SUPPLICANT_IFACE_INTERFACE, "BSSs");
300 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
301 if_path, DBUS_INTERFACE_PROPERTIES,
302 "Get", params, __netconfig_wifi_wps_get_bsss_result);
304 ERR("Fail to method: Get");
312 void netconfig_wifi_wps_signal_scandone(void)
314 wps_bss_list_count = 0;
315 _netconfig_wifi_wps_get_bsss();
317 netconfig_is_device_scanning = FALSE;
319 __netconfig_wps_set_mode(FALSE);
322 void netconfig_wifi_wps_signal_scanaborted(void)
324 wps_bss_list_count = 0;
325 netconfig_is_wps_scan_aborted = TRUE;
326 _netconfig_wifi_wps_get_bsss();
328 netconfig_is_device_scanning = FALSE;
330 __netconfig_wps_set_mode(FALSE);
333 static int __netconfig_wifi_wps_request_scan(const char *if_path)
335 GDBusConnection *connection = NULL;
336 GVariant *message = NULL;
337 GVariantBuilder *builder = NULL;
338 const char *key1 = "Type";
339 const char *val1 = "passive";
342 if_path = netconfig_wifi_get_supplicant_interface();
344 if (if_path == NULL) {
345 DBG("Fail to get wpa_supplicant DBus path");
349 connection = netdbus_get_connection();
350 if (connection == NULL) {
351 ERR("Failed to get GDBusconnection");
355 builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
356 g_variant_builder_add(builder, "{sv}", key1, g_variant_new_string(val1));
357 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
358 g_variant_builder_unref(builder);
360 g_dbus_connection_call(connection,
363 SUPPLICANT_INTERFACE ".Interface",
367 G_DBUS_CALL_FLAGS_NONE,
368 NETCONFIG_WPS_DBUS_REPLY_TIMEOUT,
369 netdbus_get_cancellable(),
373 netconfig_is_device_scanning = TRUE;
375 g_variant_unref(message);
376 /* Clear bss_info_list for the next scan result */
377 if (wps_bss_info_list) {
378 g_slist_free_full(wps_bss_info_list, g_free);
379 wps_bss_info_list = NULL;
382 netconfig_is_wps_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_wps_request_scan(path);
406 ERR("Failed to create interface, Error: %d[%s]", error->code, error->message);
407 __netconfig_wps_set_mode(FALSE);
408 wifi_power_driver_and_supplicant(FALSE);
411 g_variant_unref(message);
414 static int __netconfig_wifi_wps_create_interface(void)
416 GDBusConnection *connection = NULL;
417 GVariant *message = NULL;
418 GVariantBuilder *builder = NULL;
419 const char *key = "Ifname";
420 const char *val = WIFI_IFNAME;
422 connection = netdbus_get_connection();
423 if (connection == NULL) {
424 DBG("Failed to get GDBusconnection");
428 builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
429 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(val));
430 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
432 g_dbus_connection_call(connection,
435 SUPPLICANT_INTERFACE,
439 G_DBUS_CALL_FLAGS_NONE,
440 NETCONFIG_WPS_DBUS_REPLY_TIMEOUT,
441 netdbus_get_cancellable(),
442 (GAsyncReadyCallback) __netconfig_wifi_interface_create_result,
445 g_variant_unref(message);
450 static int __netconfig_wifi_wps_scan(void)
453 wifi_tech_state_e wifi_tech_state;
455 if (netconfig_is_device_scanning == TRUE)
458 wifi_tech_state = wifi_state_get_technology_state();
459 if (wifi_tech_state <= NETCONFIG_WIFI_TECH_OFF)
460 err = wifi_power_driver_and_supplicant(TRUE);
462 if (err < 0 && err != -EALREADY)
465 netconfig_is_device_scanning = TRUE;
467 DBG("WPS scan requested");
468 if (wifi_tech_state >= NETCONFIG_WIFI_TECH_POWERED) {
469 if (netconfig_wifi_get_scanning() == TRUE)
472 netconfig_wifi_bgscan_start(TRUE);
474 if (wifi_tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
475 __netconfig_wifi_wps_request_scan(NULL);
477 err = __netconfig_wifi_wps_create_interface();
483 gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context)
485 int err, enabled = 0;
486 wifi_tech_state_e tech_state;
488 g_return_val_if_fail(wifi != NULL, FALSE);
490 if (netconfig_is_wifi_tethering_on() == TRUE) {
491 ERR("Wi-Fi Tethering is enabled");
492 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "TetheringEnabled");
496 #if !defined TIZEN_WEARABLE
497 if (netconfig_wifi_is_bgscan_paused()) {
498 ERR("Scan is paused");
499 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "ScanPaused");
504 tech_state = wifi_state_get_technology_state();
505 if (tech_state <= NETCONFIG_WIFI_TECH_OFF) {
506 #if !defined TIZEN_WEARABLE
507 vconf_get_int(VCONF_WIFI_ALWAYS_ALLOW_SCANNING, &enabled);
513 netconfig_error_permission_denied(context);
518 __netconfig_wps_set_mode(TRUE);
520 err = __netconfig_wifi_wps_scan();
522 if (err == -EINPROGRESS)
523 netconfig_error_inprogress(context);
525 netconfig_error_wifi_driver_failed(context);
530 wifi_complete_request_wps_scan(wifi, context);
535 static void __interface_wps_cancel_result(GObject *source_object,
536 GAsyncResult *res, gpointer user_data)
539 GDBusConnection *conn = NULL;
540 GError *error = NULL;
542 conn = G_DBUS_CONNECTION (source_object);
543 reply = g_dbus_connection_call_finish(conn, res, &error);
547 ERR("Fail to request status [%d: %s]",
548 error->code, error->message);
551 ERR("Fail torequest status");
554 DBG("Successfully M/W--->WPAS: Interface.WPS.Cancel Method");
557 g_variant_unref(reply);
558 netconfig_gdbus_pending_call_unref();
561 static gboolean __netconfig_wifi_invoke_wps_cancel()
563 gboolean reply = FALSE;
564 const char *if_path = NULL;
566 if_path = netconfig_wifi_get_supplicant_interface();
567 if (if_path == NULL) {
568 DBG("Fail to get wpa_supplicant DBus path");
572 DBG("M/W--->WPAS: Interface.WPS.Cancel Method");
574 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
575 if_path, SUPPLICANT_IFACE_WPS,
576 "Cancel", NULL, __interface_wps_cancel_result);
579 ERR("M/W--->WPAS: Interface.WPS.Cancel Method Failed");
585 gboolean netconfig_iface_wifi_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation **context)
588 DBG("Received WPS PBC Cancel Request");
589 g_return_val_if_fail(wifi != NULL, FALSE);
590 return __netconfig_wifi_invoke_wps_cancel();
592 /*Not supported for mobile and Wearable profile*/