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.
26 #include "netsupplicant.h"
27 #include "wifi-ssid-scan.h"
28 #include "wifi-background-scan.h"
30 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
31 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
34 WIFI_SECURITY_UNKNOWN = 0x00,
35 WIFI_SECURITY_NONE = 0x01,
36 WIFI_SECURITY_WEP = 0x02,
37 WIFI_SECURITY_PSK = 0x03,
38 WIFI_SECURITY_IEEE8021X = 0x04,
42 unsigned char ssid[33];
43 unsigned char bssid[6];
44 wifi_security_e security;
49 static gboolean g_ssid_scan_state = FALSE;
50 static GSList *bss_info_list = NULL;
51 static guint ssid_scan_timer = 0;
52 static char *g_ssid = NULL;
54 static void __check_security(const char *str_keymgmt, bss_info_t *bss_info)
56 INFO("keymgmt : %s", str_keymgmt);
58 if (g_strcmp0(str_keymgmt, "ieee8021x") == 0)
59 bss_info->security = WIFI_SECURITY_IEEE8021X;
60 else if (g_strcmp0(str_keymgmt, "wpa-psk") == 0)
61 bss_info->security = WIFI_SECURITY_PSK;
62 else if (g_strcmp0(str_keymgmt, "wpa-psk-sha256") == 0)
63 bss_info->security = WIFI_SECURITY_PSK;
64 else if (g_strcmp0(str_keymgmt, "wpa-ft-psk") == 0)
65 bss_info->security = WIFI_SECURITY_PSK;
66 else if (g_strcmp0(str_keymgmt, "wpa-ft-eap") == 0)
67 bss_info->security = WIFI_SECURITY_IEEE8021X;
68 else if (g_strcmp0(str_keymgmt, "wpa-eap") == 0)
69 bss_info->security = WIFI_SECURITY_IEEE8021X;
70 else if (g_strcmp0(str_keymgmt, "wpa-eap-sha256") == 0)
71 bss_info->security = WIFI_SECURITY_IEEE8021X;
72 else if (g_strcmp0(str_keymgmt, "wps") == 0)
76 static gboolean __ssid_scan_timeout(gpointer data)
78 wifi_ssid_scan_emit_scan_completed();
83 static void _start_ssid_scan_timer(void)
85 INFO("Wi-Fi SSID scan started");
86 g_ssid_scan_state = TRUE;
88 netconfig_start_timer_seconds(5, __ssid_scan_timeout, NULL, &ssid_scan_timer);
91 static void _stop_ssid_scan_timer(void)
93 INFO("Wi-Fi SSID scan finished");
94 g_ssid_scan_state = FALSE;
96 netconfig_stop_timer(&ssid_scan_timer);
99 static void _parse_keymgmt_message(GVariant *param, bss_info_t *bss_info)
105 g_variant_get(param, "a{sv}", &iter1);
106 while (g_variant_iter_loop(iter1, "{sv}", &key, &var)) {
107 if (g_strcmp0(key, "KeyMgmt") == 0) {
109 g_variant_get(var, "as", &iter2);
111 while (g_variant_iter_loop(iter2, "s", &str)) {
114 __check_security(str, bss_info);
116 g_variant_iter_free(iter2);
120 g_variant_iter_free(iter1);
125 static gboolean _request_ssid_scan(const char *object_path, const char *ssid)
127 /* TODO: Revise following code */
129 GDBusConnection *connection = NULL;
130 GVariant *reply = NULL;
131 GVariant *params = NULL;
132 GError *error = NULL;
133 GVariantBuilder *builder1 = NULL;
134 GVariantBuilder *builder2 = NULL;
135 GVariantBuilder *builder3 = NULL;
136 const gchar *key1 = "Type";
137 const gchar *val1 = "active";
138 const gchar *key2 = "SSIDs";
141 connection = netdbus_get_connection();
142 if (connection == NULL) {
143 DBG("Failed to get GDBusconnection");
147 builder1 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
148 g_variant_builder_add(builder1, "{sv}", key1, g_variant_new_string(val1));
150 builder2 = g_variant_builder_new(G_VARIANT_TYPE("aay"));
151 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
153 for (i = 0; i < strlen(ssid); i++)
154 g_variant_builder_add(builder3, "y", ssid[i]);
156 g_variant_builder_add(builder2, "@ay", g_variant_builder_end(builder3));
157 g_variant_builder_add(builder1, "{sv}", key2, g_variant_builder_end(builder2));
159 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder1));
161 g_variant_builder_unref(builder1);
162 g_variant_builder_unref(builder2);
163 g_variant_builder_unref(builder3);
165 reply = g_dbus_connection_call_sync(
169 SUPPLICANT_INTERFACE ".Interface",
173 G_DBUS_CALL_FLAGS_NONE,
174 NETCONFIG_DBUS_REPLY_TIMEOUT,
175 netdbus_get_cancellable(),
180 ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. "
181 "DBus error [%d: %s]", error->code, error->message);
184 ERR("Error!!! Failed to get properties");
192 g_ssid = g_strdup(ssid);
194 g_variant_unref(reply);
199 static void _emit_ssid_scan_completed(void)
201 GVariantBuilder *builder = NULL;
203 const char *prop_ssid = "ssid";
204 const char *prop_bssid = "bssid";
205 char bssid_buf[18] = {0,};
206 char *bssid_str = bssid_buf;
207 const char *prop_security = "security";
208 const char *prop_wps = "wps";
210 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
211 for (list = bss_info_list; list != NULL; list = list->next) {
212 bss_info_t *bss_info = (bss_info_t *)list->data;
213 if (bss_info && g_strcmp0((char *)bss_info->ssid, g_ssid) == 0) {
214 const gchar *ssid = (char *)bss_info->ssid;
215 const gchar *bssid = (gchar *)&bss_info->bssid[0];
216 wifi_security_e security = bss_info->security;
217 gboolean wps = bss_info->wps;
218 DBG("BSS found; SSID:%s security:%d WPS:%d", ssid, security, wps);
221 snprintf(bssid_str, sizeof(bssid_buf), MACSTR, MAC2STR(bssid));
222 DBG("BSSID: %s", bssid_str);
224 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
225 g_variant_builder_add(builder, "{sv}", prop_bssid,
226 g_variant_new_string(bssid));
227 g_variant_builder_add(builder, "{sv}", prop_security, g_variant_new_int32(security));
229 g_variant_builder_add(builder, "{sv}", prop_wps, g_variant_new_boolean(wps));
233 wifi_emit_specific_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
236 g_variant_builder_unref(builder);
238 if (bss_info_list != NULL) {
239 g_slist_free_full(bss_info_list, g_free);
240 bss_info_list = NULL;
243 if (g_ssid != NULL) {
248 INFO("SpecificScanCompleted");
253 gboolean wifi_ssid_scan(const char *ssid)
256 static char *scan_ssid = NULL;
258 netconfig_wifi_bgscan_stop();
261 if (scan_ssid != NULL)
263 scan_ssid = g_strdup(ssid);
266 if (scan_ssid == NULL)
269 if_path = netconfig_wifi_get_supplicant_interface();
270 if (if_path == NULL) {
271 DBG("Fail to get wpa_supplicant DBus path");
275 if (netconfig_wifi_get_scanning() == TRUE) {
276 DBG("Wi-Fi scan in progress, %s scan will be delayed", scan_ssid);
281 g_slist_free_full(bss_info_list, g_free);
282 bss_info_list = NULL;
285 INFO("Start Wi-Fi scan with %s(%d)", scan_ssid, strlen(scan_ssid));
286 if (_request_ssid_scan(if_path, (const char *)scan_ssid) == TRUE) {
287 _start_ssid_scan_timer();
294 if (scan_ssid != NULL) {
299 netconfig_wifi_bgscan_start(FALSE);
304 gboolean wifi_ssid_scan_get_state(void)
306 return g_ssid_scan_state;
309 void wifi_ssid_scan_emit_scan_completed(void)
311 if (g_ssid_scan_state != TRUE)
314 _stop_ssid_scan_timer();
315 _emit_ssid_scan_completed();
318 void wifi_ssid_scan_add_bss(GVariant *message)
324 bss_info_t *bss_info;
326 if (g_ssid_scan_state != TRUE)
329 INFO("NEW BSS added");
331 if (message == NULL) {
332 DBG("Message does not have parameters");
337 INFO("Object path of BSS added is %s", path);
339 bss_info = g_try_new0(bss_info_t, 1);
340 if (bss_info == NULL)
343 g_variant_get(message, "(oa{sv})", &path, &iter);
344 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
345 if (g_strcmp0(key, "SSID") == 0) {
348 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
349 if (ssid != NULL && ssid_len > 0 && ssid_len < 33)
350 memcpy(bss_info->ssid, ssid, ssid_len);
352 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
353 } else if (g_strcmp0(key, "Privacy") == 0) {
354 gboolean privacy = FALSE;
355 privacy = g_variant_get_boolean(value);
356 bss_info->privacy = privacy;
357 } else if ((g_strcmp0(key, "RSN") == 0) || (g_strcmp0(key, "WPA") == 0)) {
358 _parse_keymgmt_message(value, bss_info);
359 } else if (g_strcmp0(key, "IEs") == 0) {
362 ie = g_variant_get_fixed_array(value, &ie_len, sizeof(guchar));
363 DBG("The IE : %s", ie);
364 } else if(g_strcmp0(key, "BSSID") == 0) {
368 bssid = g_variant_get_fixed_array(value, &bssid_len, sizeof(guchar));
369 if(bssid != NULL && bssid_len == 6)
370 memcpy(bss_info->bssid,bssid,bssid_len);
374 g_variant_iter_free(iter);
378 if (bss_info->ssid[0] == '\0') {
383 if (bss_info->security == WIFI_SECURITY_UNKNOWN) {
384 if (bss_info->privacy == TRUE)
385 bss_info->security = WIFI_SECURITY_WEP;
387 bss_info->security = WIFI_SECURITY_NONE;
390 bss_info_list = g_slist_append(bss_info_list, bss_info);
393 gboolean handle_request_specific_scan(Wifi *wifi,
394 GDBusMethodInvocation *context, const gchar *ssid)
396 gboolean result = FALSE;
398 g_return_val_if_fail(wifi != NULL, FALSE);
399 g_return_val_if_fail(ssid != NULL, FALSE);
401 result = wifi_ssid_scan((const char *)ssid);
404 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "FailSpecificScan");
406 wifi_complete_request_specific_scan(wifi, context);