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.
24 #include "netsupplicant.h"
25 #include "wifi-ssid-scan.h"
26 #include "wifi-background-scan.h"
28 enum netconfig_wifi_security {
29 WIFI_SECURITY_UNKNOWN = 0x00,
30 WIFI_SECURITY_NONE = 0x01,
31 WIFI_SECURITY_WEP = 0x02,
32 WIFI_SECURITY_PSK = 0x03,
33 WIFI_SECURITY_IEEE8021X = 0x04,
37 unsigned char ssid[33];
38 enum netconfig_wifi_security security;
43 static gboolean wifi_ssid_scan_state = FALSE;
44 static GSList *wifi_bss_info_list = NULL;
45 static guint netconfig_wifi_ssid_scan_timer = 0;
46 static char *g_ssid = NULL;
48 static gboolean __netconfig_wifi_ssid_scan_timeout(gpointer data)
50 netconfig_wifi_notify_ssid_scan_done();
55 static void __netconfig_wifi_ssid_scan_started(void)
57 INFO("Wi-Fi SSID scan started");
58 wifi_ssid_scan_state = TRUE;
60 netconfig_start_timer_seconds(5,
61 __netconfig_wifi_ssid_scan_timeout,
63 &netconfig_wifi_ssid_scan_timer);
66 static void __netconfig_wifi_ssid_scan_finished(void)
68 INFO("Wi-Fi SSID scan finished");
69 wifi_ssid_scan_state = FALSE;
71 netconfig_stop_timer(&netconfig_wifi_ssid_scan_timer);
74 static gboolean __netconfig_wifi_invoke_ssid_scan(
75 const char *object_path, const char *ssid)
77 /* TODO: Revise following code */
79 #define NETCONFIG_DBUS_REPLY_TIMEOUT (10 * 1000)
80 GDBusConnection *connection = NULL;
81 GVariant *reply = NULL;
82 GVariant *params = NULL;
84 GVariantBuilder *builder1 = NULL;
85 GVariantBuilder *builder2 = NULL;
86 GVariantBuilder *builder3 = NULL;
87 const gchar *key1 = "Type";
88 const gchar *val1 = "active";
89 const gchar *key2 = "SSIDs";
92 connection = netconfig_gdbus_get_connection();
93 if (connection == NULL) {
94 DBG("Failed to get GDBusconnection");
98 builder1 = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
99 g_variant_builder_add(builder1, "{sv}", key1, g_variant_new_string(val1));
101 builder2 = g_variant_builder_new(G_VARIANT_TYPE ("aay"));
102 builder3 = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
104 for (i = 0; i < strlen(ssid); i++) {
105 g_variant_builder_add (builder3, "y", ssid[i]);
108 g_variant_builder_add(builder2, "@ay", g_variant_builder_end(builder3));
109 g_variant_builder_add(builder1, "{sv}", key2, g_variant_builder_end(builder2));
111 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder1));
113 g_variant_builder_unref(builder1);
114 g_variant_builder_unref(builder2);
115 g_variant_builder_unref(builder3);
117 reply = g_dbus_connection_call_sync(
121 SUPPLICANT_INTERFACE ".Interface",
125 G_DBUS_CALL_FLAGS_NONE,
126 NETCONFIG_DBUS_REPLY_TIMEOUT,
127 netconfig_gdbus_get_gdbus_cancellable(),
132 ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. "
133 "DBus error [%d: %s]", error->code, error->message);
136 ERR("Error!!! Failed to get properties");
141 if (g_ssid != NULL) {
145 g_ssid = g_strdup(ssid);
147 g_variant_unref(reply);
152 static void __netconfig_wifi_notify_ssid_scan_done(void)
154 GVariantBuilder *builder = NULL;
156 const char *prop_ssid = "ssid";
157 const char *prop_security = "security";
158 const char *prop_wps = "wps";
160 builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
161 for (list = wifi_bss_info_list; list != NULL; list = list->next) {
162 struct bss_info_t *bss_info = (struct bss_info_t *)list->data;
163 if (bss_info && g_strcmp0((char *)bss_info->ssid, g_ssid) == 0) {
164 const gchar *ssid = (char *)bss_info->ssid;
165 enum netconfig_wifi_security security = bss_info->security;
166 gboolean wps = bss_info->wps;
167 DBG("BSS found; SSID:%s security:%d WPS:%d", ssid, security, wps);
170 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new("(s)", ssid));
172 g_variant_builder_add(builder, "{sv}", prop_security, g_variant_new_int32(security));
174 g_variant_builder_add(builder, "{sv}", prop_wps, g_variant_new_boolean(wps));
178 wifi_emit_specific_scan_completed((Wifi *)get_netconfig_wifi_object(),
179 g_variant_builder_end(builder));
182 g_variant_builder_unref(builder);
184 if (wifi_bss_info_list != NULL) {
185 g_slist_free_full(wifi_bss_info_list, g_free);
186 wifi_bss_info_list = NULL;
189 if (g_ssid != NULL) {
194 INFO("SpecificScanCompleted");
199 static void __netconfig_wifi_check_security(const char *str_keymgmt, struct bss_info_t *bss_data)
201 INFO("keymgmt : %s", str_keymgmt);
203 if (strcmp(str_keymgmt, "ieee8021x") == 0) {
204 bss_data->security = WIFI_SECURITY_IEEE8021X;
205 } else if (strcmp(str_keymgmt, "wpa-psk") == 0) {
206 bss_data->security = WIFI_SECURITY_PSK;
207 } else if (strcmp(str_keymgmt, "wpa-psk-sha256") == 0) {
208 bss_data->security = WIFI_SECURITY_PSK;
209 } else if (strcmp(str_keymgmt, "wpa-ft-psk") == 0) {
210 bss_data->security = WIFI_SECURITY_PSK;
211 } else if (strcmp(str_keymgmt, "wpa-ft-eap") == 0) {
212 bss_data->security = WIFI_SECURITY_IEEE8021X;
213 } else if (strcmp(str_keymgmt, "wpa-eap") == 0) {
214 bss_data->security = WIFI_SECURITY_IEEE8021X;
215 } else if (strcmp(str_keymgmt, "wpa-eap-sha256") == 0) {
216 bss_data->security = WIFI_SECURITY_IEEE8021X;
217 } else if (strcmp(str_keymgmt, "wps") == 0) {
218 bss_data->wps = TRUE;
222 static void __netconfig_wifi_parse_keymgmt_message(GVariant *param, struct bss_info_t *bss_data)
228 g_variant_get(param, "a{sv}", &iter1);
229 while (g_variant_iter_loop(iter1, "{sv}", &key, &var)) {
230 if (g_strcmp0(key, "KeyMgmt") == 0) {//check this :iterate
232 g_variant_get(var, "as", &iter2);
234 while (g_variant_iter_loop(iter2, "s", &str)) {
238 __netconfig_wifi_check_security(str, bss_data);
240 g_variant_iter_free (iter2);
244 g_variant_iter_free (iter1);
249 gboolean netconfig_wifi_get_ssid_scan_state(void)
251 return wifi_ssid_scan_state;
254 void netconfig_wifi_notify_ssid_scan_done(void)
256 if (netconfig_wifi_get_ssid_scan_state() != TRUE)
259 __netconfig_wifi_ssid_scan_finished();
261 __netconfig_wifi_notify_ssid_scan_done();
264 void netconfig_wifi_bss_added(GVariant *message)
268 const gchar *path = NULL;
270 struct bss_info_t *bss_info;
272 if (netconfig_wifi_get_ssid_scan_state() != TRUE)
275 INFO("NEW BSS added");
277 if (message == NULL) {
278 DBG("Message does not have parameters");
284 INFO("Object path of BSS added is %s",path);
286 bss_info = g_try_new0(struct bss_info_t, 1);
287 if (bss_info == NULL)
290 g_variant_get(message, "(oa{sv})", &path, &iter);
291 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
292 if (g_strcmp0(key, "SSID") == 0) {
295 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
296 if (ssid_len > 0 && ssid_len < 33)
297 memcpy(bss_info->ssid, ssid, ssid_len);
299 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
300 } else if (g_strcmp0(key, "Privacy") == 0) {
301 gboolean privacy = FALSE;
302 privacy = g_variant_get_boolean(value);
303 bss_info->privacy = privacy;
304 } else if ((g_strcmp0(key, "RSN") == 0) || (g_strcmp0(key, "WPA") == 0)) {
305 __netconfig_wifi_parse_keymgmt_message(value, bss_info);
306 } else if (g_strcmp0(key, "IEs") == 0) {
309 ie = g_variant_get_fixed_array(value, &ie_len, sizeof(guchar));
310 DBG("The IE : %s",ie);
314 g_variant_iter_free(iter);
316 if (bss_info->ssid[0] == '\0') {
321 if (bss_info->security == WIFI_SECURITY_UNKNOWN) {
322 if (bss_info->privacy == TRUE)
323 bss_info->security = WIFI_SECURITY_WEP;
325 bss_info->security = WIFI_SECURITY_NONE;
328 wifi_bss_info_list = g_slist_append(wifi_bss_info_list, bss_info);
331 gboolean netconfig_wifi_ssid_scan(const char *ssid)
334 static char *scan_ssid = NULL;
336 netconfig_wifi_bgscan_stop();
340 scan_ssid = g_strdup(ssid);
343 if (scan_ssid == NULL)
346 if_path = netconfig_wifi_get_supplicant_interface();
347 if (if_path == NULL) {
348 DBG("Fail to get wpa_supplicant DBus path");
352 if (netconfig_wifi_get_scanning() == TRUE) {
353 DBG("Wi-Fi scan in progress, %s scan will be delayed", scan_ssid);
358 if (wifi_bss_info_list) {
359 g_slist_free_full(wifi_bss_info_list, g_free);
360 wifi_bss_info_list = NULL;
363 INFO("Start Wi-Fi scan with %s(%d)", scan_ssid, strlen(scan_ssid));
364 if (__netconfig_wifi_invoke_ssid_scan(if_path,
365 (const char *)scan_ssid) == TRUE) {
366 __netconfig_wifi_ssid_scan_started();
375 if (scan_ssid != NULL) {
380 netconfig_wifi_bgscan_start(FALSE);
385 gboolean handle_request_specific_scan(Wifi *wifi,
386 GDBusMethodInvocation *context, const gchar *ssid)
388 gboolean result = FALSE;
390 g_return_val_if_fail(wifi != NULL, FALSE);
391 g_return_val_if_fail(ssid != NULL, FALSE);
393 result = netconfig_wifi_ssid_scan((const char *)ssid);
395 if (result != TRUE) {
396 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "FailSpecificScan");
398 wifi_complete_request_wps_scan(wifi, context);