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 <vconf-keys.h>
30 #include "wifi-agent.h"
31 #include "wifi-state.h"
32 #include "wifi-eap-config.h"
33 #include "network-state.h"
34 #include "network-accessibility.h"
35 #include "wifi-key-encryption.h"
37 #define NETCONFIG_AGENT_FIELD_NAME "Name"
38 #define NETCONFIG_AGENT_FIELD_SSID "SSID"
39 #define NETCONFIG_AGENT_FIELD_IDENTITY "Identity"
40 #define NETCONFIG_AGENT_FIELD_PASSPHRASE "Passphrase"
41 #define NETCONFIG_AGENT_FIELD_WPS "WPS"
42 #define NETCONFIG_AGENT_FIELD_WPS_PBC "WPS_PBC"
43 #define NETCONFIG_AGENT_FIELD_WPS_PIN "WPS_PIN"
44 #if defined TIZEN_CAPTIVE_PORTAL
45 #define NETCONFIG_AGENT_FIELD_USERNAME "Username"
46 #define NETCONFIG_AGENT_FIELD_PASSWORD "Password"
49 #define NETCONFIG_AGENT_ERR_CONNECT_FAILED "connect-failed"
51 struct netconfig_wifi_agent {
57 #if defined TIZEN_CAPTIVE_PORTAL
64 static struct netconfig_wifi_agent agent;
66 static void __netconfig_agent_clear_fields(void)
69 g_byte_array_free(agent.ssid, TRUE);
71 g_free(agent.identity);
72 g_free(agent.passphrase);
73 g_free(agent.wps_pin);
74 #if defined TIZEN_CAPTIVE_PORTAL
75 g_free(agent.username);
76 g_free(agent.password);
81 agent.identity = NULL;
82 agent.passphrase = NULL;
84 #if defined TIZEN_CAPTIVE_PORTAL
85 agent.username = NULL;
86 agent.password = NULL;
88 agent.wps_pbc = FALSE;
91 int connman_register_agent(void)
93 GVariant *reply = NULL;
94 GVariant *params = NULL;
96 params = g_variant_new("(o)", NETCONFIG_WIFI_PATH);
97 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
98 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
99 "RegisterAgent", params);
102 ERR("Fail to register agent");
105 g_variant_unref(reply);
107 INFO("Registered to connman agent successfully");
112 int connman_unregister_agent(void)
114 gboolean reply = FALSE;
115 GVariant *param = NULL;
116 const char *path = NETCONFIG_WIFI_PATH;
118 param = g_variant_new("(o)", path);
120 DBG("ConnMan agent unregister");
122 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
123 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
124 "UnregisterAgent", param, NULL);
127 ERR("Fail to unregister agent");
129 /* Clearing the agent fields */
130 __netconfig_agent_clear_fields();
135 gboolean netconfig_wifi_set_agent_field_for_eap_network(
136 const char *name, const char *identity, const char *passphrase)
143 __netconfig_agent_clear_fields();
145 name_len = strlen(name);
146 agent.ssid = g_byte_array_sized_new(name_len);
147 agent.ssid->len = name_len;
148 memcpy(agent.ssid->data, name, name_len + 1);
151 agent.identity = g_strdup(identity);
154 agent.passphrase = g_strdup(passphrase);
156 gchar *enc_data = NULL;
157 enc_data = _netconfig_encrypt_passphrase(agent.passphrase);
160 ERR("Failed to encrypt the passphrase");
162 g_free(agent.passphrase);
163 agent.passphrase = enc_data;
166 DBG("Successfully configured for EAP network");
171 gboolean handle_set_field(NetConnmanAgent *connman_agent,
172 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
174 GError *error = NULL;
178 gboolean updated = FALSE;
179 gboolean reply = FALSE;
181 g_return_val_if_fail(connman_agent != NULL, TRUE);
183 DBG("Set agent fields for %s", service);
185 if (netconfig_is_wifi_profile(service) != TRUE) {
186 error = g_error_new(G_DBUS_ERROR,
187 G_DBUS_ERROR_AUTH_FAILED,
188 CONNMAN_ERROR_INTERFACE ".InvalidService");
190 g_dbus_method_invocation_return_gerror(context, error);
191 g_clear_error(&error);
196 __netconfig_agent_clear_fields();
197 g_variant_get(fields, "a{sv}", &iter);
198 while (g_variant_iter_loop(iter, "{sv}", &field, &value)) {
199 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0) {
200 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
201 agent.passphrase = g_strdup(g_variant_get_string(value, NULL));
204 DBG("Field [%s] - [%s]", field, agent.passphrase);
206 if (agent.passphrase == NULL)
209 if (netconfig_check_passphrase(service, agent.passphrase) == FALSE) {
210 ERR("Invalid passphrase");
212 g_free(agent.passphrase);
213 agent.passphrase = NULL;
219 gchar *enc_data = NULL;
220 enc_data = _netconfig_encrypt_passphrase(agent.passphrase);
223 ERR("Failed to encrypt the passphrase");
227 g_free(agent.passphrase);
228 agent.passphrase = enc_data;
230 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PBC) == 0) {
231 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) &&
232 g_strcmp0(g_variant_get_string(value, NULL), "enable") == 0) {
233 agent.wps_pbc = TRUE;
236 DBG("Field [%s] - [%d]", field, agent.wps_pbc);
238 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PIN) == 0) {
239 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
240 agent.wps_pin = g_strdup(g_variant_get_string(value, NULL));
243 DBG("Field [%s] - [%s]", field, agent.wps_pin);
245 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0) {
246 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
247 agent.name = g_strdup(g_variant_get_string(value, NULL));
250 DBG("Field [%s] - [%s]", field, agent.name);
252 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0) {
253 if (agent.ssid != NULL) {
254 g_byte_array_free(agent.ssid, TRUE);
258 if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) {
261 GByteArray *array = g_byte_array_new();
263 g_variant_get(value, "ay", &iter1);
264 while (g_variant_iter_loop(iter1, "y", &char_value))
265 g_byte_array_append(array, &char_value, 1);
266 g_variant_iter_free(iter1);
267 if (array != NULL && (array->len > 0)) {
268 agent.ssid = g_byte_array_sized_new(array->len);
269 agent.ssid->len = array->len;
270 memcpy(agent.ssid->data, array->data, array->len);
273 DBG("Field [%s] - []", field);
276 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0) {
277 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
278 agent.identity = g_strdup(g_variant_get_string(value, NULL));
281 DBG("Field [%s] - [%s]", field, agent.identity);
283 #if defined TIZEN_CAPTIVE_PORTAL
284 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_USERNAME) == 0) {
285 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
286 agent.username = g_strdup(g_variant_get_string(value, NULL));
289 DBG("Field [%s] - [%s]", field, agent.username);
291 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSWORD) == 0) {
292 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
293 agent.password = g_strdup(g_variant_get_string(value, NULL));
296 DBG("Field [%s] - [%s]", field, agent.password);
302 if (updated == TRUE) {
303 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
304 service, CONNMAN_SERVICE_INTERFACE, "Connect",
305 NULL, __netconfig_wifi_connect_reply);
307 g_dbus_method_invocation_return_value(context, NULL);
309 ERR("Fail to connect Wi-Fi");
310 __netconfig_agent_clear_fields();
311 error = g_error_new(G_DBUS_ERROR,
312 G_DBUS_ERROR_AUTH_FAILED,
313 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
315 g_dbus_method_invocation_return_gerror(context, error);
316 g_clear_error(&error);
319 error = g_error_new(G_DBUS_ERROR,
320 G_DBUS_ERROR_AUTH_FAILED,
321 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
323 g_dbus_method_invocation_return_gerror(context, error);
324 g_clear_error(&error);
328 ERR("Fail to connect Wi-Fi");
329 __netconfig_agent_clear_fields();
331 g_variant_iter_free(iter);
333 net_connman_agent_complete_set_field(connman_agent, context);
337 gboolean handle_request_input(NetConnmanAgent *connman_agent,
338 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
342 GVariant *r_value = NULL;
343 GVariant *out_table = NULL;
344 gboolean updated = FALSE;
345 GVariantBuilder *builder = NULL;
347 g_return_val_if_fail(connman_agent != NULL, TRUE);
352 DBG("Agent fields requested for service: %s", service);
354 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
356 g_variant_get(fields, "a{sv}", &iter);
357 while (g_variant_iter_loop(iter, "{sv}", &field, &r_value)) {
359 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0 &&
360 agent.passphrase != NULL) {
361 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSPHRASE,
362 g_variant_new_string(agent.passphrase));
365 DBG("Setting [%s] - [%s]", field, agent.passphrase);
366 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS) == 0 &&
367 (agent.wps_pbc == TRUE || agent.wps_pin != NULL)) {
368 if (agent.wps_pbc == TRUE) {
369 /* Sending empty string for WPS push button method */
370 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(""));
373 DBG("Setting empty string for [%s]", field);
374 } else if (agent.wps_pin != NULL) {
375 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(agent.wps_pin));
378 DBG("Setting string [%s] - [%s]", field, agent.wps_pin);
380 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0 &&
381 agent.name != NULL) {
382 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_NAME, g_variant_new_string(agent.name));
385 DBG("Settings [%s] - [%s]", field, agent.name);
386 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0 &&
387 agent.ssid != NULL) {
389 GVariantBuilder *builder1 = NULL;
390 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
392 for (i = 0; i < (agent.ssid->len); i++)
393 g_variant_builder_add(builder1, "y", agent.ssid->data[i]);
395 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_SSID, g_variant_builder_end(builder1));
396 if (builder1 != NULL)
397 g_variant_builder_unref(builder1);
400 DBG("Settings [%s] - []", field);
401 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0 &&
402 agent.identity != NULL) {
403 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_IDENTITY, g_variant_new_string(agent.identity));
406 DBG("Settings [%s] - [%s]", field, agent.identity);
407 #if defined TIZEN_CAPTIVE_PORTAL
408 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_USERNAME) == 0 &&
409 agent.username != NULL) {
410 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_USERNAME, g_variant_new_string(agent.username));
413 DBG("Settings [%s] - [%s]", field, agent.username);
414 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSWORD) == 0 &&
415 agent.password != NULL) {
416 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSWORD, g_variant_new_string(agent.password));
419 DBG("Settings [%s] - [%s]", field, agent.password);
424 out_table = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
427 g_variant_builder_unref(builder);
429 g_variant_iter_free(iter);
432 if (NULL == out_table) {
433 net_connman_agent_complete_request_input(connman_agent, context, out_table);
439 g_dbus_method_invocation_return_value(context, out_table);
441 GError *error = NULL;
442 error = g_error_new(G_DBUS_ERROR,
443 G_DBUS_ERROR_AUTH_FAILED,
444 "net.connman.Agent.Error.Canceled");
446 g_dbus_method_invocation_return_gerror(context, error);
447 g_clear_error(&error);
450 __netconfig_agent_clear_fields();
456 gboolean handle_report_error(NetConnmanAgent *connman_agent,
457 GDBusMethodInvocation *context, const gchar *service, const gchar *error)
459 g_return_val_if_fail(connman_agent != NULL, TRUE);
461 net_connman_agent_complete_report_error(connman_agent, context);
462 DBG("Agent error for service[%s] - [%s]", service, error);
464 /* Do something when it failed to make a connection */
469 #if defined TIZEN_CAPTIVE_PORTAL
470 #if defined TIZEN_WEARABLE
471 #define QUERY_FOR_INTERNET_INTERVAL 2
472 #define TIMER_THRESHOLD 4
474 #define QUERY_FOR_INTERNET_INTERVAL 20
475 #define TIMER_THRESHOLD 120
478 static gboolean is_monitor_notifier_registered = FALSE;
480 #if defined TIZEN_WEARABLE
481 static gboolean is_portal_msg_shown = FALSE;
484 struct poll_timer_data {
490 static struct poll_timer_data timer_data = {
491 QUERY_FOR_INTERNET_INTERVAL, 0, NULL};
493 static gboolean __check_ignore_portal_list(const char * ssid)
497 int ignore_ap_count = 0;
502 DBG("checking ssid [%s]", ssid);
504 DBG("csc string [%s]", def_str);
505 gchar ** ignore_ap_list = g_strsplit(def_str, ",", 0);
506 ignore_ap_count = g_strv_length(ignore_ap_list);
507 for (i = 0; i < ignore_ap_count; i++) {
508 DBG("[%d] - [%s]", i, ignore_ap_list[i]);
509 if (strncmp(ignore_ap_list[i], ssid, strlen(ssid)) == 0) {
510 g_strfreev(ignore_ap_list);
515 g_strfreev(ignore_ap_list);
519 static void __wifi_state_monitor(wifi_service_state_e state,
522 static wifi_state_notifier wifi_state_monitor_notifier = {
523 .wifi_state_changed = __wifi_state_monitor,
527 static void __wifi_state_monitor(wifi_service_state_e state,
530 DBG("Wi-Fi state: %x", state);
532 if (state == NETCONFIG_WIFI_CONNECTED)
535 if (is_monitor_notifier_registered == TRUE) {
536 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
537 is_monitor_notifier_registered = FALSE;
540 #if defined TIZEN_WEARABLE
541 is_portal_msg_shown = FALSE;
544 /* suspend if Internet check activity in progress */
545 if (timer_data.timer_id == 0)
548 netconfig_stop_timer(&timer_data.timer_id);
549 netconfig_stop_internet_check();
551 DBG("Stopped Internet accessibility check");
554 static gboolean __netconfig_wifi_portal_login_timeout(gpointer data)
556 char *service_profile = NULL;
557 GVariant *reply = NULL;
561 struct poll_timer_data *timer = (struct poll_timer_data *)data;
565 if (TRUE == netconfig_get_internet_status()) {
566 if (is_monitor_notifier_registered == TRUE) {
567 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
568 is_monitor_notifier_registered = FALSE;
571 DBG("Portal logged in successfully and update ConnMan state");
572 return FALSE; /* to stop the timer */
574 if (timer->time_elapsed >= TIMER_THRESHOLD) {
575 DBG("Login failed, update ConnMan");
577 if (is_monitor_notifier_registered == TRUE) {
578 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
579 is_monitor_notifier_registered = FALSE;
582 /* Disconnect and forget the AP */
583 service_profile = (char*) netconfig_get_default_profile();
584 if (service_profile && netconfig_is_wifi_profile(service_profile)) {
585 /* Now forget the AP*/
586 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
587 service_profile, CONNMAN_SERVICE_INTERFACE, "Remove",
591 g_variant_unref(reply);
593 ERR("Failed to forget the AP ");
596 if (NETCONFIG_WIFI_CONNECTED ==
597 wifi_state_get_service_state()) {
598 /* check Internet availability by sending and receiving data*/
599 netconfig_check_internet_accessibility();
600 /* Returning TRUE itself is enough to restart the timer */
601 timer->time_elapsed = timer->time_elapsed +
602 QUERY_FOR_INTERNET_INTERVAL;
611 static void __netconfig_wifi_portal_login_timer_start(struct poll_timer_data
614 DBG("__netconfig_wifi_browser_start_timer...starting timer");
619 netconfig_stop_timer(&(data->timer_id));
621 /* Timer logic: After successful launch of browser, we would check for
622 * Internet status for every 20s until a threshold of 120s
625 data->time_elapsed = QUERY_FOR_INTERNET_INTERVAL;
626 netconfig_start_timer_seconds(QUERY_FOR_INTERNET_INTERVAL,
627 __netconfig_wifi_portal_login_timeout, data, &(data->timer_id));
631 gboolean handle_request_browser(NetConnmanAgent *connman_agent,
632 GDBusMethodInvocation *context, const gchar *service, const gchar *url)
634 #if defined TIZEN_CAPTIVE_PORTAL
635 gboolean ignore_portal = FALSE;
636 const char * ssid = NULL;
638 g_return_val_if_fail(connman_agent != NULL, TRUE);
640 DBG("service[%s] - url[%s]", service, url);
642 ssid = netconfig_wifi_get_connected_essid(netconfig_get_default_profile());
644 ERR("Connected AP name is NULL!!");
645 net_connman_agent_complete_request_browser(connman_agent, context);
649 ignore_portal = __check_ignore_portal_list(ssid);
651 if (ignore_portal == TRUE) {
652 net_connman_agent_complete_request_browser(connman_agent, context);
655 /* Register for Wifi state change notifier*/
656 if (is_monitor_notifier_registered == FALSE) {
657 wifi_state_notifier_register(&wifi_state_monitor_notifier);
658 is_monitor_notifier_registered = TRUE;
661 netconfig_send_notification_to_net_popup(NETCONFIG_ADD_PORTAL_NOTI, ssid);
663 timer_data.time_elapsed = 0;
664 __netconfig_wifi_portal_login_timer_start(&timer_data);
666 net_connman_agent_complete_request_browser(connman_agent, context);
669 GError *error = NULL;
670 error = g_error_new(G_DBUS_ERROR,
671 G_DBUS_ERROR_AUTH_FAILED,
672 CONNMAN_ERROR_INTERFACE ".NotSupported");
674 g_dbus_method_invocation_return_gerror(context, error);
675 g_clear_error(&error);