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"
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 wifi_security_e security;
43 static gboolean g_ssid_scan_state = FALSE;
44 static GSList *bss_info_list = NULL;
45 static guint ssid_scan_timer = 0;
46 static char *g_ssid = NULL;
48 static void __check_security(const char *str_keymgmt, bss_info_t *bss_info)
50 INFO("keymgmt : %s", str_keymgmt);
52 if (g_strcmp0(str_keymgmt, "ieee8021x") == 0)
53 bss_info->security = WIFI_SECURITY_IEEE8021X;
54 else if (g_strcmp0(str_keymgmt, "wpa-psk") == 0)
55 bss_info->security = WIFI_SECURITY_PSK;
56 else if (g_strcmp0(str_keymgmt, "wpa-psk-sha256") == 0)
57 bss_info->security = WIFI_SECURITY_PSK;
58 else if (g_strcmp0(str_keymgmt, "wpa-ft-psk") == 0)
59 bss_info->security = WIFI_SECURITY_PSK;
60 else if (g_strcmp0(str_keymgmt, "wpa-ft-eap") == 0)
61 bss_info->security = WIFI_SECURITY_IEEE8021X;
62 else if (g_strcmp0(str_keymgmt, "wpa-eap") == 0)
63 bss_info->security = WIFI_SECURITY_IEEE8021X;
64 else if (g_strcmp0(str_keymgmt, "wpa-eap-sha256") == 0)
65 bss_info->security = WIFI_SECURITY_IEEE8021X;
66 else if (g_strcmp0(str_keymgmt, "wps") == 0)
70 static gboolean __ssid_scan_timeout(gpointer data)
72 wifi_ssid_scan_emit_scan_completed();
77 static void _start_ssid_scan_timer(void)
79 INFO("Wi-Fi SSID scan started");
80 g_ssid_scan_state = TRUE;
82 netconfig_start_timer_seconds(5, __ssid_scan_timeout, NULL, &ssid_scan_timer);
85 static void _stop_ssid_scan_timer(void)
87 INFO("Wi-Fi SSID scan finished");
88 g_ssid_scan_state = FALSE;
90 netconfig_stop_timer(&ssid_scan_timer);
93 static void _parse_keymgmt_message(GVariant *param, bss_info_t *bss_info)
99 g_variant_get(param, "a{sv}", &iter1);
100 while (g_variant_iter_loop(iter1, "{sv}", &key, &var)) {
101 if (g_strcmp0(key, "KeyMgmt") == 0) {
103 g_variant_get(var, "as", &iter2);
105 while (g_variant_iter_loop(iter2, "s", &str)) {
108 __check_security(str, bss_info);
110 g_variant_iter_free(iter2);
114 g_variant_iter_free(iter1);
119 static gboolean _request_ssid_scan(const char *object_path, const char *ssid)
121 /* TODO: Revise following code */
123 GDBusConnection *connection = NULL;
124 GVariant *reply = NULL;
125 GVariant *params = NULL;
126 GError *error = NULL;
127 GVariantBuilder *builder1 = NULL;
128 GVariantBuilder *builder2 = NULL;
129 GVariantBuilder *builder3 = NULL;
130 const gchar *key1 = "Type";
131 const gchar *val1 = "active";
132 const gchar *key2 = "SSIDs";
135 connection = netdbus_get_connection();
136 if (connection == NULL) {
137 DBG("Failed to get GDBusconnection");
141 builder1 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
142 g_variant_builder_add(builder1, "{sv}", key1, g_variant_new_string(val1));
144 builder2 = g_variant_builder_new(G_VARIANT_TYPE("aay"));
145 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
147 for (i = 0; i < strlen(ssid); i++)
148 g_variant_builder_add(builder3, "y", ssid[i]);
150 g_variant_builder_add(builder2, "@ay", g_variant_builder_end(builder3));
151 g_variant_builder_add(builder1, "{sv}", key2, g_variant_builder_end(builder2));
153 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder1));
155 g_variant_builder_unref(builder1);
156 g_variant_builder_unref(builder2);
157 g_variant_builder_unref(builder3);
159 reply = g_dbus_connection_call_sync(
163 SUPPLICANT_INTERFACE ".Interface",
167 G_DBUS_CALL_FLAGS_NONE,
168 NETCONFIG_DBUS_REPLY_TIMEOUT,
169 netdbus_get_cancellable(),
174 ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. "
175 "DBus error [%d: %s]", error->code, error->message);
178 ERR("Error!!! Failed to get properties");
186 g_ssid = g_strdup(ssid);
188 g_variant_unref(reply);
193 static void _emit_ssid_scan_completed(void)
195 GVariantBuilder *builder = NULL;
197 const char *prop_ssid = "ssid";
198 const char *prop_security = "security";
199 const char *prop_wps = "wps";
201 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
202 for (list = bss_info_list; list != NULL; list = list->next) {
203 bss_info_t *bss_info = (bss_info_t *)list->data;
204 if (bss_info && g_strcmp0((char *)bss_info->ssid, g_ssid) == 0) {
205 const gchar *ssid = (char *)bss_info->ssid;
206 wifi_security_e security = bss_info->security;
207 gboolean wps = bss_info->wps;
208 DBG("BSS found; SSID:%s security:%d WPS:%d", ssid, security, wps);
209 g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
210 g_variant_builder_add(builder, "{sv}", prop_security, g_variant_new_int32(security));
212 g_variant_builder_add(builder, "{sv}", prop_wps, g_variant_new_boolean(wps));
216 wifi_emit_specific_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
219 g_variant_builder_unref(builder);
221 if (bss_info_list != NULL) {
222 g_slist_free_full(bss_info_list, g_free);
223 bss_info_list = NULL;
226 if (g_ssid != NULL) {
231 INFO("SpecificScanCompleted");
236 gboolean wifi_ssid_scan(const char *ssid)
239 static char *scan_ssid = NULL;
241 netconfig_wifi_bgscan_stop();
244 if (scan_ssid != NULL)
246 scan_ssid = g_strdup(ssid);
249 if (scan_ssid == NULL)
252 if_path = netconfig_wifi_get_supplicant_interface();
253 if (if_path == NULL) {
254 DBG("Fail to get wpa_supplicant DBus path");
258 if (netconfig_wifi_get_scanning() == TRUE) {
259 DBG("Wi-Fi scan in progress, %s scan will be delayed", scan_ssid);
265 g_slist_free_full(bss_info_list, g_free);
266 bss_info_list = NULL;
269 INFO("Start Wi-Fi scan with %s(%d)", scan_ssid, strlen(scan_ssid));
270 if (_request_ssid_scan(if_path, (const char *)scan_ssid) == TRUE) {
271 _start_ssid_scan_timer();
278 if (scan_ssid != NULL) {
283 netconfig_wifi_bgscan_start(FALSE);
288 gboolean wifi_ssid_scan_get_state(void)
290 return g_ssid_scan_state;
293 void wifi_ssid_scan_emit_scan_completed(void)
295 if (g_ssid_scan_state != TRUE)
298 _stop_ssid_scan_timer();
299 _emit_ssid_scan_completed();
302 void wifi_ssid_scan_add_bss(GVariant *message)
308 bss_info_t *bss_info;
310 if (g_ssid_scan_state != TRUE)
313 INFO("NEW BSS added");
315 if (message == NULL) {
316 DBG("Message does not have parameters");
321 INFO("Object path of BSS added is %s", path);
323 bss_info = g_try_new0(bss_info_t, 1);
324 if (bss_info == NULL)
327 g_variant_get(message, "(oa{sv})", &path, &iter);
328 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
329 if (g_strcmp0(key, "SSID") == 0) {
332 ssid = g_variant_get_fixed_array(value, &ssid_len, sizeof(guchar));
333 if (ssid != NULL && ssid_len > 0 && ssid_len < 33)
334 memcpy(bss_info->ssid, ssid, ssid_len);
336 memset(bss_info->ssid, 0, sizeof(bss_info->ssid));
337 } else if (g_strcmp0(key, "Privacy") == 0) {
338 gboolean privacy = FALSE;
339 privacy = g_variant_get_boolean(value);
340 bss_info->privacy = privacy;
341 } else if ((g_strcmp0(key, "RSN") == 0) || (g_strcmp0(key, "WPA") == 0)) {
342 _parse_keymgmt_message(value, bss_info);
343 } else if (g_strcmp0(key, "IEs") == 0) {
346 ie = g_variant_get_fixed_array(value, &ie_len, sizeof(guchar));
347 DBG("The IE : %s", ie);
351 g_variant_iter_free(iter);
355 if (bss_info->ssid[0] == '\0') {
360 if (bss_info->security == WIFI_SECURITY_UNKNOWN) {
361 if (bss_info->privacy == TRUE)
362 bss_info->security = WIFI_SECURITY_WEP;
364 bss_info->security = WIFI_SECURITY_NONE;
367 bss_info_list = g_slist_append(bss_info_list, bss_info);
370 gboolean handle_request_specific_scan(Wifi *wifi,
371 GDBusMethodInvocation *context, const gchar *ssid)
373 gboolean result = FALSE;
375 g_return_val_if_fail(wifi != NULL, FALSE);
376 g_return_val_if_fail(ssid != NULL, FALSE);
378 result = wifi_ssid_scan((const char *)ssid);
381 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "FailSpecificScan");
383 wifi_complete_request_specific_scan(wifi, context);