2 * Network Configuration Module
4 * Copyright (c) 2012-2013 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.
24 #include "netsupplicant.h"
25 #include "wifi-ssid-scan.h"
26 #include "wifi-background-scan.h"
29 unsigned char ssid[32];
30 enum netconfig_wifi_security security;
35 static gboolean wifi_ssid_scan_state = FALSE;
36 static GSList *wifi_bss_info_list = NULL;
37 static guint netconfig_wifi_ssid_scan_timer = 0;
39 static gboolean __netconfig_wifi_ssid_scan_timeout(gpointer data)
41 netconfig_wifi_notify_ssid_scan_done();
46 static void __netconfig_wifi_ssid_scan_started(void)
48 INFO("Wi-Fi SSID scan started");
49 wifi_ssid_scan_state = TRUE;
51 netconfig_start_timer_seconds(
53 __netconfig_wifi_ssid_scan_timeout,
55 &netconfig_wifi_ssid_scan_timer);
58 static void __netconfig_wifi_ssid_scan_finished(void)
60 INFO("Wi-Fi SSID scan finished");
61 wifi_ssid_scan_state = FALSE;
63 netconfig_stop_timer(&netconfig_wifi_ssid_scan_timer);
66 static gboolean __netconfig_wifi_invoke_ssid_scan(
67 const char *object_path, const char *ssid)
69 /* TODO: Revise following code */
71 #define NETCONFIG_DBUS_REPLY_TIMEOUT (10 * 1000)
73 DBusConnection *connection = NULL;
74 DBusMessage *message = NULL;
75 DBusMessage *reply = NULL;
76 DBusMessageIter iter, dict, entry;
77 DBusMessageIter value, array, array2;
80 const char *key1 = "Type";
81 const char *val1 = "active";
82 const char *key2 = "SSIDs";
84 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
85 if (connection == NULL) {
86 ERR("Error!!! Failed to get system DBus");
90 message = dbus_message_new_method_call(SUPPLICANT_SERVICE,
91 object_path, SUPPLICANT_INTERFACE ".Interface", "Scan");
92 if (message == NULL) {
93 ERR("Error!!! DBus method call fail");
97 dbus_message_iter_init_append(message, &iter);
98 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
99 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
100 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
101 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
103 dbus_message_iter_open_container(&dict,
104 DBUS_TYPE_DICT_ENTRY, NULL, &entry);
105 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key1);
107 dbus_message_iter_open_container(&entry,
108 DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &value);
109 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &val1);
111 dbus_message_iter_close_container(&entry, &value);
112 dbus_message_iter_close_container(&dict, &entry);
114 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
115 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key2);
117 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
118 DBUS_TYPE_ARRAY_AS_STRING
119 DBUS_TYPE_ARRAY_AS_STRING
120 DBUS_TYPE_BYTE_AS_STRING,
122 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
123 DBUS_TYPE_ARRAY_AS_STRING
124 DBUS_TYPE_BYTE_AS_STRING,
126 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &array2);
128 dbus_message_iter_append_fixed_array(&array2, DBUS_TYPE_BYTE, &ssid, strlen(ssid));
130 dbus_message_iter_close_container(&array, &array2);
131 dbus_message_iter_close_container(&value, &array);
132 dbus_message_iter_close_container(&entry, &value);
133 dbus_message_iter_close_container(&dict, &entry);
134 dbus_message_iter_close_container(&iter, &dict);
136 dbus_error_init(&error);
138 reply = dbus_connection_send_with_reply_and_block(connection, message,
139 NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
142 if (dbus_error_is_set(&error) == TRUE) {
143 ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. "
144 "DBus error [%s: %s]", error.name, error.message);
146 dbus_error_free(&error);
149 ERR("Error!!! Failed to get properties");
154 MessageType = dbus_message_get_type(reply);
155 if (MessageType == DBUS_MESSAGE_TYPE_ERROR) {
156 const char *err_msg = dbus_message_get_error_name(reply);
157 ERR("Error!!! Error message received %s", err_msg);
161 dbus_message_unref(message);
162 dbus_message_unref(reply);
163 dbus_connection_unref(connection);
169 dbus_message_unref(message);
172 dbus_message_unref(reply);
174 if (connection != NULL)
175 dbus_connection_unref(connection);
180 static void __netconfig_wifi_notify_ssid_scan_done(void)
183 DBusConnection *connection = NULL;
184 DBusMessageIter dict, type, array, value;
186 char *prop_ssid = "ssid";
187 char *prop_security = "security";
188 const char *sig_name = "SpecificScanCompleted";
190 dbus_error_init(&error);
192 connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
193 if (connection == NULL) {
194 /* TODO: If this occurs then UG should be informed abt SCAN fail. CHECK THIS. */
195 ERR("Error!!! Failed to get system DBus, error [%s]", error.message);
196 dbus_error_free(&error);
198 g_slist_free_full(wifi_bss_info_list, g_free);
199 wifi_bss_info_list = NULL;
204 signal = dbus_message_new_signal(NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE, sig_name);
205 if (signal == NULL) {
206 /* TODO: If this occurs then UG should be informed abt SCAN fail. CHECK THIS. */
207 dbus_connection_unref(connection);
209 g_slist_free_full(wifi_bss_info_list, g_free);
210 wifi_bss_info_list = NULL;
215 dbus_message_iter_init_append(signal, &array);
216 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, "{sv}", &dict);
217 GSList* list = wifi_bss_info_list;
219 struct bss_info_t *bss_info = (struct bss_info_t *)g_slist_nth_data(list, 0);
222 char *ssid = (char *)&(bss_info->ssid[0]);
223 dbus_int16_t security = bss_info->security;
224 DBG("Bss found. SSID: %s; Sec mode: %d;", ssid, security);
226 /* Lets pack the SSID */
227 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, 0, &type);
228 dbus_message_iter_append_basic(&type, DBUS_TYPE_STRING, &prop_ssid);
229 dbus_message_iter_open_container(&type, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &value);
231 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &ssid);
232 dbus_message_iter_close_container(&type, &value);
233 dbus_message_iter_close_container(&dict, &type);
235 /* Lets pack the Security */
236 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, 0, &type);
237 dbus_message_iter_append_basic(&type, DBUS_TYPE_STRING, &prop_security);
238 dbus_message_iter_open_container(&type, DBUS_TYPE_VARIANT, DBUS_TYPE_INT16_AS_STRING, &value);
240 dbus_message_iter_append_basic(&value, DBUS_TYPE_INT16, &security);
241 dbus_message_iter_close_container(&type, &value);
242 dbus_message_iter_close_container(&dict, &type);
244 list = g_slist_next(list);
247 dbus_message_iter_close_container(&array, &dict);
249 dbus_error_init(&error);
250 dbus_connection_send(connection, signal, NULL);
252 dbus_message_unref(signal);
253 dbus_connection_unref(connection);
255 g_slist_free_full(wifi_bss_info_list, g_free);
256 wifi_bss_info_list = NULL;
258 INFO("(%s)", sig_name);
261 static void __netconfig_wifi_check_security(const char *str_keymgmt, struct bss_info_t *bss_data)
263 INFO("keymgmt : %s", str_keymgmt);
265 if (strcmp(str_keymgmt, "ieee8021x") == 0) {
266 bss_data->security = WIFI_SECURITY_IEEE8021X;
267 } else if (strcmp(str_keymgmt, "wpa-psk") == 0) {
268 bss_data->security = WIFI_SECURITY_PSK;
269 } else if (strcmp(str_keymgmt, "wpa-psk-sha256") == 0) {
270 bss_data->security = WIFI_SECURITY_PSK;
271 } else if (strcmp(str_keymgmt, "wpa-ft-psk") == 0) {
272 bss_data->security = WIFI_SECURITY_PSK;
273 } else if (strcmp(str_keymgmt, "wpa-ft-eap") == 0) {
274 bss_data->security = WIFI_SECURITY_IEEE8021X;
275 } else if (strcmp(str_keymgmt, "wpa-eap") == 0) {
276 bss_data->security = WIFI_SECURITY_IEEE8021X;
277 } else if (strcmp(str_keymgmt, "wpa-eap-sha256") == 0) {
278 bss_data->security = WIFI_SECURITY_IEEE8021X;
279 } else if (strcmp(str_keymgmt, "wps") == 0) {
280 bss_data->wps = TRUE;
284 static void __netconfig_wifi_parse_keymgmt_message(DBusMessageIter *iter, struct bss_info_t *bss_data)
286 DBusMessageIter dict, entry, array, value;
289 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
292 dbus_message_iter_recurse(iter, &dict);
293 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
294 dbus_message_iter_recurse(&dict, &entry);
296 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
299 dbus_message_iter_get_basic(&entry, &key);
300 if (g_strcmp0(key, "KeyMgmt") == 0) {
301 dbus_message_iter_next(&entry);
303 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
306 dbus_message_iter_recurse(&entry, &array);
307 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
310 dbus_message_iter_recurse(&array, &value);
311 while (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
312 const char *str = NULL;
314 dbus_message_iter_get_basic(&value, &str);
318 __netconfig_wifi_check_security(str, bss_data);
319 dbus_message_iter_next(&value);
323 dbus_message_iter_next(&dict);
327 gboolean netconfig_wifi_get_ssid_scan_state(void)
329 return wifi_ssid_scan_state;
332 void netconfig_wifi_notify_ssid_scan_done(void)
334 if (netconfig_wifi_get_ssid_scan_state() != TRUE)
337 __netconfig_wifi_ssid_scan_finished();
339 __netconfig_wifi_notify_ssid_scan_done();
341 netconfig_wifi_bgscan_start();
344 void netconfig_wifi_bss_added(DBusMessage *message)
346 DBusMessageIter iter, dict, entry;
347 DBusMessageIter value, array;
349 struct bss_info_t *bss_info;
351 if (netconfig_wifi_get_ssid_scan_state() != TRUE)
354 INFO("NEW BSS added");
356 if (!dbus_message_iter_init(message, &iter)) {
357 DBG("Message does not have parameters");
361 dbus_message_iter_next(&iter);
363 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
364 DBG("Invalid message type");
368 bss_info = g_try_new0(struct bss_info_t, 1);
369 if (bss_info == NULL) {
370 DBG("Out of memory");
374 dbus_message_iter_recurse(&iter, &dict);
375 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
376 dbus_message_iter_recurse(&dict, &entry);
378 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
381 dbus_message_iter_get_basic(&entry, &key);
385 dbus_message_iter_next(&entry);
386 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
389 dbus_message_iter_recurse(&entry, &value);
391 if (g_strcmp0(key, "SSID") == 0) {
395 dbus_message_iter_recurse(&value, &array);
396 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
398 if (ssid_len > 0 && ssid_len < 33)
399 memcpy(bss_info->ssid, ssid, ssid_len);
401 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
402 } else if (g_strcmp0(key, "Privacy") == 0) {
403 dbus_bool_t privacy = FALSE;
405 dbus_message_iter_get_basic(&value, &privacy);
406 bss_info->privacy = privacy;
407 } else if ((g_strcmp0(key, "RSN") == 0) || (g_strcmp0(key, "WPA") == 0)) {
409 __netconfig_wifi_parse_keymgmt_message(&value, bss_info);
410 } else if (g_strcmp0(key, "IEs") == 0) {
414 dbus_message_iter_recurse(&value, &array);
415 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
418 dbus_message_iter_next(&dict);
421 if (bss_info->ssid[0] == 0)
424 if (bss_info->security == WIFI_SECURITY_UNKNOWN) {
425 if (bss_info->privacy == TRUE)
426 bss_info->security = WIFI_SECURITY_WEP;
428 bss_info->security = WIFI_SECURITY_NONE;
431 wifi_bss_info_list = g_slist_append(wifi_bss_info_list, bss_info);
438 gboolean netconfig_wifi_ssid_scan(const char *ssid)
440 char object_path[DBUS_PATH_MAX_BUFLEN] = { 0, };
441 char *path_ptr = &object_path[0];
442 static char *scan_ssid = NULL;
444 netconfig_wifi_bgscan_stop();
448 scan_ssid = g_strdup(ssid);
451 if (scan_ssid == NULL) {
452 netconfig_wifi_bgscan_start();
456 if (netconfig_wifi_get_scanning() == TRUE) {
457 DBG("Wi-Fi scan is in progress! SSID %s scan will be delayed",
462 INFO("Start SSID Scan with %s", scan_ssid);
464 if (wifi_bss_info_list) {
465 g_slist_free_full(wifi_bss_info_list, g_free);
466 wifi_bss_info_list = NULL;
469 if (netconfig_wifi_get_supplicant_interface(&path_ptr) != TRUE) {
470 DBG("Fail to get wpa_supplicant DBus path");
474 if (__netconfig_wifi_invoke_ssid_scan(
475 (const char *)object_path, (const char *)scan_ssid) == TRUE) {
476 __netconfig_wifi_ssid_scan_started();
487 gboolean netconfig_iface_wifi_request_specific_scan(NetconfigWifi *wifi,
488 gchar *ssid, GError **error)
490 g_return_val_if_fail(wifi != NULL, FALSE);
491 g_return_val_if_fail(ssid != NULL, FALSE);
493 netconfig_wifi_ssid_scan((const char *)ssid);