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 struct netconfig_wifi_wps {
59 static struct netconfig_wifi_wps wifi_wps;
61 static GSList *wps_bss_info_list = NULL;
63 static void __netconfig_wps_set_mode(gboolean enable)
65 if (netconfig_is_wps_enabled == enable)
68 netconfig_is_wps_enabled = enable;
71 gboolean netconfig_wifi_is_wps_enabled(void)
73 return netconfig_is_wps_enabled;
76 void netconfig_wifi_notify_wps_credentials(const char *ssid, gsize ssid_len, const char *wps_key)
78 GVariantBuilder *builder;
80 const char *sig_name = "WpsCredentials";
81 const char *prop_ssid = "ssid";
82 const char *prop_key = "key";
83 GVariantBuilder *rawssid_builder = NULL;
86 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
87 rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
88 for (i = 0; i < ssid_len; i++)
89 g_variant_builder_add(rawssid_builder, "y", ssid[i]);
90 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder));
91 g_variant_builder_unref(rawssid_builder);
92 g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new_string(wps_key));
94 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
95 g_variant_builder_unref(builder);
97 netconfig_dbus_emit_signal(NULL,
99 NETCONFIG_WIFI_INTERFACE,
103 INFO("Sent signal (%s)", sig_name);
107 void netconfig_wifi_notify_wps_completed(const char *ssid, gsize ssid_len)
109 GVariantBuilder *builder;
111 const char *sig_name = "WpsCompleted";
112 const char *prop_ssid = "ssid";
113 GVariantBuilder *rawssid_builder = NULL;
116 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
117 rawssid_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
118 for (i = 0; i < ssid_len; i++)
119 g_variant_builder_add(rawssid_builder, "y", ssid[i]);
120 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("ay", rawssid_builder));
121 g_variant_builder_unref(rawssid_builder);
123 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
124 g_variant_builder_unref(builder);
126 netconfig_dbus_emit_signal(NULL,
128 NETCONFIG_WIFI_INTERFACE,
132 INFO("Sent signal (%s)", sig_name);
136 void netconfig_wifi_notify_wps_fail_event(int config_error, int error_indication)
138 GVariantBuilder *builder;
140 const char *sig_name = "WpsFailEvent";
141 const char *prop_config_error = "config_error";
142 const char *prop_error_indication = "error_indication";
144 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
145 g_variant_builder_add(builder, "{sv}", prop_config_error, g_variant_new_int32(config_error));
146 g_variant_builder_add(builder, "{sv}", prop_error_indication, g_variant_new_int32(error_indication));
148 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
149 g_variant_builder_unref(builder);
151 netconfig_dbus_emit_signal(NULL,
153 NETCONFIG_WIFI_INTERFACE,
157 INFO("Sent signal (%s)", sig_name);
161 static void __netconfig_wifi_wps_notify_scan_done(void)
163 GVariantBuilder *builder = NULL;
164 GVariantBuilder *builder1 = NULL;
166 const char *prop_ssid = "ssid";
167 const char *prop_bssid = "bssid";
168 const char *prop_rssi = "rssi";
169 const char *prop_mode = "mode";
171 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
172 for (list = wps_bss_info_list; list != NULL; list = list->next) {
173 struct wps_bss_info_t *bss_info = (struct wps_bss_info_t *)list->data;
176 gchar bssid_buff[18] = { 0, };
177 gchar *bssid_str = bssid_buff;
178 unsigned char *ssid = (unsigned char *)bss_info->ssid;
179 int ssid_len = (int)bss_info->ssid_len;
180 int rssi = (int)bss_info->rssi;
181 int mode = (int)bss_info->mode;
183 g_snprintf(bssid_buff, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
184 bss_info->bssid[0], bss_info->bssid[1], bss_info->bssid[2],
185 bss_info->bssid[3], bss_info->bssid[4], bss_info->bssid[5]);
187 DBG("BSS found; SSID %s, BSSID %s, RSSI %d MODE %d", ssid, bssid_str, rssi, mode);
189 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
190 for (i = 0; i < ssid_len; i++)
191 g_variant_builder_add(builder1, "y", ssid[i]);
192 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_builder_end(builder1));
193 g_variant_builder_unref(builder1);
195 g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid_str));
196 g_variant_builder_add(builder, "{sv}", prop_rssi, g_variant_new_int32(rssi));
197 g_variant_builder_add(builder, "{sv}", prop_mode, g_variant_new_int32(mode));
201 wifi_emit_wps_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
202 g_variant_builder_unref(builder);
204 if (wps_bss_info_list != NULL)
205 g_slist_free_full(wps_bss_info_list, g_free);
207 wps_bss_info_list = NULL;
208 wps_bss_list_count = 0;
209 INFO("WpsScanCompleted");
214 static void __netconfig_wifi_wps_get_bss_info_result(
215 GObject *source_object, GAsyncResult *res, gpointer user_data)
217 GVariant *reply = NULL;
221 struct wps_bss_info_t *bss_info;
222 GDBusConnection *conn = NULL;
223 GError *error = NULL;
225 conn = G_DBUS_CONNECTION(source_object);
226 reply = g_dbus_connection_call_finish(conn, res, &error);
229 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
234 bss_info = g_try_new0(struct wps_bss_info_t, 1);
235 if (bss_info == NULL)
238 g_variant_get(reply, "(a{sv})", &iter);
239 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
241 if (g_strcmp0(key, "BSSID") == 0) {
245 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
246 if (bssid_len == NETCONFIG_BSSID_LEN)
247 memcpy(bss_info->bssid, bssid, bssid_len);
248 } else if (g_strcmp0(key, "SSID") == 0) {
252 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
253 if (ssid != NULL && ssid_len > 0 && ssid_len <= NETCONFIG_SSID_LEN) {
254 memcpy(bss_info->ssid, ssid, ssid_len);
255 bss_info->ssid_len = ssid_len;
257 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
258 bss_info->ssid_len = 0;
260 } else if (g_strcmp0(key, "Mode") == 0) {
263 g_variant_get(value, "s", &mode);
267 if (g_strcmp0(mode, "infrastructure") == 0)
269 else if (g_strcmp0(mode, "ad-hoc") == 0)
275 } else if (g_strcmp0(key, "Signal") == 0) {
278 signal = g_variant_get_int16(value);
279 bss_info->rssi = signal;
284 if (bss_info->ssid[0] == '\0')
287 wps_bss_info_list = g_slist_append(wps_bss_info_list, bss_info);
289 g_variant_iter_free(iter);
292 g_variant_unref(reply);
294 netconfig_gdbus_pending_call_unref();
296 wps_bss_list_count--;
297 if (wps_bss_list_count <= 0) {
298 __netconfig_wifi_wps_notify_scan_done();
300 if (netconfig_is_wps_scan_aborted == FALSE)
301 wifi_power_driver_and_supplicant(FALSE);
305 static void __netconfig_wifi_wps_get_bss_info(const char *path, int index)
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,
314 "GetAll", param, __netconfig_wifi_wps_get_bss_info_result);
316 ERR("Fail to invoke_dbus_method_nonblock GetAll");
321 static void __netconfig_wifi_wps_get_bsss_result(GObject *source_object,
322 GAsyncResult *res, gpointer user_data)
324 GVariant *reply = NULL;
325 GVariant *value = NULL;
326 GVariantIter *iter = NULL;
327 GDBusConnection *conn = NULL;
329 gboolean counter_flag = FALSE;
330 GError *error = NULL;
332 conn = G_DBUS_CONNECTION(source_object);
333 reply = g_dbus_connection_call_finish(conn, res, &error);
335 ERR("Error code: [%d] Error message: [%s]", error->code, error->message);
340 g_variant_get(reply, "(v)", &value);
341 if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) {
342 g_variant_get(value, "ao", &iter);
343 while (g_variant_iter_next(iter, "o", &path)) {
344 if (path != NULL && g_strcmp0(path, "/") != 0) {
345 __netconfig_wifi_wps_get_bss_info(path, ++wps_bss_list_count);
356 g_variant_iter_free(iter);
359 g_variant_unref(value);
363 g_variant_unref(reply);
365 netconfig_gdbus_pending_call_unref();
367 /* Send WpsScanCompleted signal even when the BSS count is 0 */
368 if (wps_bss_list_count <= 0 && counter_flag == FALSE) {
369 __netconfig_wifi_wps_notify_scan_done();
371 if (netconfig_is_wps_scan_aborted == FALSE)
372 wifi_power_driver_and_supplicant(FALSE);
376 static int _netconfig_wifi_wps_get_bsss(void)
378 gboolean reply = FALSE;
379 const char *if_path = NULL;
380 GVariant *params = NULL;
382 if_path = netconfig_wifi_get_supplicant_interface();
383 if (if_path == NULL) {
384 DBG("Fail to get wpa_supplicant DBus path");
388 params = g_variant_new("(ss)", SUPPLICANT_IFACE_INTERFACE, "BSSs");
390 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
391 if_path, DBUS_INTERFACE_PROPERTIES,
392 "Get", params, __netconfig_wifi_wps_get_bsss_result);
394 ERR("Fail to method: Get");
402 void netconfig_wifi_wps_signal_scandone(void)
404 wps_bss_list_count = 0;
405 _netconfig_wifi_wps_get_bsss();
407 netconfig_is_device_scanning = FALSE;
409 __netconfig_wps_set_mode(FALSE);
412 void netconfig_wifi_wps_signal_scanaborted(void)
414 wps_bss_list_count = 0;
415 netconfig_is_wps_scan_aborted = TRUE;
416 _netconfig_wifi_wps_get_bsss();
418 netconfig_is_device_scanning = FALSE;
420 __netconfig_wps_set_mode(FALSE);
423 static int __netconfig_wifi_wps_request_scan(const char *if_path)
425 GDBusConnection *connection = NULL;
426 GVariant *message = NULL;
427 GVariantBuilder *builder = NULL;
428 const char *key1 = "Type";
429 const char *val1 = "passive";
432 if_path = netconfig_wifi_get_supplicant_interface();
434 if (if_path == NULL) {
435 DBG("Fail to get wpa_supplicant DBus path");
439 connection = netdbus_get_connection();
440 if (connection == NULL) {
441 ERR("Failed to get GDBusconnection");
445 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
446 g_variant_builder_add(builder, "{sv}", key1, g_variant_new_string(val1));
447 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
448 g_variant_builder_unref(builder);
450 g_dbus_connection_call(connection,
453 SUPPLICANT_INTERFACE ".Interface",
457 G_DBUS_CALL_FLAGS_NONE,
458 NETCONFIG_WPS_DBUS_REPLY_TIMEOUT,
459 netdbus_get_cancellable(),
463 netconfig_is_device_scanning = TRUE;
465 g_variant_unref(message);
466 /* Clear bss_info_list for the next scan result */
467 if (wps_bss_info_list) {
468 g_slist_free_full(wps_bss_info_list, g_free);
469 wps_bss_info_list = NULL;
472 netconfig_is_wps_scan_aborted = FALSE;
477 static void __netconfig_wifi_interface_create_result(
478 GObject *source_object, GAsyncResult *res, gpointer user_data)
482 GDBusConnection *conn = NULL;
483 GError *error = NULL;
485 conn = G_DBUS_CONNECTION(source_object);
487 message = g_dbus_connection_call_finish(conn, res, &error);
489 g_variant_get(message, "(o)", &path);
492 __netconfig_wifi_wps_request_scan(path);
495 } else if (NULL != strstr(error->message, ".InterfaceExists")) {
496 INFO("Error Message %s %s", error->message, path);
497 g_variant_get(message, "(o)", &path);
499 __netconfig_wifi_wps_request_scan(path);
502 __netconfig_wifi_wps_request_scan(NULL);
504 ERR("Failed to create interface, Error: %d[%s]", error->code, error->message);
505 __netconfig_wps_set_mode(FALSE);
506 wifi_power_driver_and_supplicant(FALSE);
509 g_variant_unref(message);
512 static int __netconfig_wifi_wps_create_interface(void)
514 GDBusConnection *connection = NULL;
515 GVariant *message = NULL;
516 GVariantBuilder *builder = NULL;
517 const char *key = "Ifname";
518 const char *val = WIFI_IFNAME;
520 connection = netdbus_get_connection();
521 if (connection == NULL) {
522 DBG("Failed to get GDBusconnection");
526 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
527 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(val));
528 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
530 g_dbus_connection_call(connection,
533 SUPPLICANT_INTERFACE,
537 G_DBUS_CALL_FLAGS_NONE,
538 NETCONFIG_WPS_DBUS_REPLY_TIMEOUT,
539 netdbus_get_cancellable(),
540 (GAsyncReadyCallback) __netconfig_wifi_interface_create_result,
543 g_variant_unref(message);
548 static int __netconfig_wifi_wps_scan(void)
551 wifi_tech_state_e wifi_tech_state;
553 if (netconfig_is_device_scanning == TRUE)
556 wifi_tech_state = wifi_state_get_technology_state();
557 if (wifi_tech_state <= NETCONFIG_WIFI_TECH_OFF)
558 err = wifi_power_driver_and_supplicant(TRUE);
560 if (err < 0 && err != -EALREADY)
563 netconfig_is_device_scanning = TRUE;
565 DBG("WPS scan requested");
566 if (wifi_tech_state >= NETCONFIG_WIFI_TECH_POWERED) {
567 if (netconfig_wifi_get_scanning() == TRUE)
570 netconfig_wifi_bgscan_start(TRUE);
572 if (wifi_tech_state == NETCONFIG_WIFI_TECH_CONNECTED)
573 __netconfig_wifi_wps_request_scan(NULL);
575 err = __netconfig_wifi_wps_create_interface();
581 gboolean handle_request_wps_scan(Wifi *wifi, GDBusMethodInvocation *context)
583 int err, enabled = 0;
584 wifi_tech_state_e tech_state;
586 g_return_val_if_fail(wifi != NULL, FALSE);
588 if (netconfig_is_wifi_tethering_on() == TRUE) {
589 ERR("Wi-Fi Tethering is enabled");
590 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "TetheringEnabled");
594 #if !defined TIZEN_WEARABLE
595 if (netconfig_wifi_is_bgscan_paused()) {
596 ERR("Scan is paused");
597 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_NO_SERVICE, "ScanPaused");
602 tech_state = wifi_state_get_technology_state();
603 if (tech_state <= NETCONFIG_WIFI_TECH_OFF) {
604 #if !defined TIZEN_WEARABLE
605 netconfig_vconf_get_int(VCONF_WIFI_ALWAYS_ALLOW_SCANNING, &enabled);
611 netconfig_error_permission_denied(context);
616 __netconfig_wps_set_mode(TRUE);
618 err = __netconfig_wifi_wps_scan();
620 if (err == -EINPROGRESS)
621 netconfig_error_inprogress(context);
623 netconfig_error_wifi_driver_failed(context);
628 wifi_complete_request_wps_scan(wifi, context);
632 static void interface_wps_start_result(GObject *source_object,
633 GAsyncResult *res, gpointer user_data)
636 GDBusConnection *conn = NULL;
637 GError *error = NULL;
639 conn = G_DBUS_CONNECTION(source_object);
640 reply = g_dbus_connection_call_finish(conn, res, &error);
644 ERR("Fail to request status [%d: %s]",
645 error->code, error->message);
648 ERR("Fail torequest status");
651 DBG("Successfully M/W--->WPAS: Interface.WPS.Start Method");
654 g_variant_unref(reply);
655 netconfig_gdbus_pending_call_unref();
658 static void __netconfig_wifi_invoke_wps_connect(GObject *source_object,
659 GAsyncResult *res, gpointer user_data)
661 GVariant *message = NULL;
662 GVariantBuilder *builder = NULL;
663 const char *role = "enrollee", *type, *key;
664 const char *if_path = NULL;
665 gboolean reply = FALSE;
668 if_path = netconfig_wifi_get_supplicant_interface();
670 if (if_path == NULL) {
671 DBG("Fail to get wpa_supplicant DBus path");
675 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
678 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(role));
682 if (wifi_wps.pbc == TRUE)
687 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(type));
689 if (wifi_wps.pin != NULL) {
691 g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(wifi_wps.pin));
693 message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
694 g_variant_builder_unref(builder);
696 DBG("[net-config]: TizenMW-->WPAS: .Interface.WPS.Start");
697 reply = netconfig_supplicant_invoke_dbus_method_nonblock(
700 SUPPLICANT_IFACE_WPS,
703 (GAsyncReadyCallback) interface_wps_start_result);
711 static gboolean __netconfig_wifi_invoke_wps_process_credentials(const char *object_path)
713 gboolean reply = FALSE;
714 GVariant *params = NULL;
715 const char *interface = SUPPLICANT_IFACE_WPS;
716 const char *key = "ProcessCredentials";
717 gboolean credentials = TRUE;
718 GVariant *var = NULL;
720 var = g_variant_new_boolean(credentials);
721 params = g_variant_new("(ssv)", interface, key, var);
723 INFO("[net-config]: TizenMW-->WPAS: .Set");
724 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
725 object_path, DBUS_INTERFACE_PROPERTIES,
726 "Set", params, __netconfig_wifi_invoke_wps_connect);
729 ERR("M/W--->WPAS: Interface.WPS.Set Method Failed");
734 gboolean netconfig_wifi_wps_connect()
736 const char *if_path = NULL;
738 if_path = netconfig_wifi_get_supplicant_interface();
739 if (if_path == NULL) {
740 DBG("Fail to get wpa_supplicant DBus path");
744 if (__netconfig_wifi_invoke_wps_process_credentials(if_path) == TRUE) {
745 ERR("Wi-Fi WPS Connect started");
753 static void __interface_wps_cancel_result(GObject *source_object,
754 GAsyncResult *res, gpointer user_data)
757 GDBusConnection *conn = NULL;
758 GError *error = NULL;
760 conn = G_DBUS_CONNECTION(source_object);
761 reply = g_dbus_connection_call_finish(conn, res, &error);
765 ERR("Fail to request status [%d: %s]",
766 error->code, error->message);
769 ERR("Fail torequest status");
772 DBG("Successfully M/W--->WPAS: Interface.WPS.Cancel Method");
775 g_variant_unref(reply);
776 netconfig_gdbus_pending_call_unref();
779 static gboolean __netconfig_wifi_invoke_wps_cancel()
781 gboolean reply = FALSE;
782 const char *if_path = NULL;
784 if_path = netconfig_wifi_get_supplicant_interface();
785 if (if_path == NULL) {
786 DBG("Fail to get wpa_supplicant DBus path");
790 DBG("M/W--->WPAS: Interface.WPS.Cancel Method");
792 reply = netconfig_invoke_dbus_method_nonblock(SUPPLICANT_SERVICE,
793 if_path, SUPPLICANT_IFACE_WPS,
794 "Cancel", NULL, __interface_wps_cancel_result);
797 ERR("M/W--->WPAS: Interface.WPS.Cancel Method Failed");
802 gboolean netconfig_get_wps_field()
807 gboolean handle_request_wps_cancel(Wifi *wifi, GDBusMethodInvocation *context)
809 INFO("Received WPS PBC Cancel Request");
810 g_return_val_if_fail(wifi != NULL, FALSE);
811 __netconfig_wifi_invoke_wps_cancel();
813 wifi_complete_request_wps_cancel(wifi, context);
817 gboolean handle_request_wps_connect(Wifi *wifi, GDBusMethodInvocation *context, gchar *param)
819 INFO("Received WPS PBC/PIN Connection Request");
821 g_return_val_if_fail(wifi != NULL, FALSE);
823 /* Checking the value of pin if param have a string "PBC"
824 * in that scenario PBC will trigger otherwise PIN Connection */
826 if (g_strcmp0(param, "PBC") == 0) {
830 wifi_wps.pin = g_strdup(param);
831 wifi_wps.pbc = FALSE;
834 netconfig_wifi_wps_connect();
836 wifi_complete_request_wps_connect(wifi, context);