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.
25 #include <vconf-keys.h>
31 #include "wifi-agent.h"
32 #include "wifi-state.h"
33 #include "wifi-eap-config.h"
34 #include "network-state.h"
35 #include "network-accessibility.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"
45 #define NETCONFIG_AGENT_ERR_CONNECT_FAILED "connect-failed"
47 struct netconfig_wifi_agent {
56 static struct netconfig_wifi_agent agent;
58 static void __netconfig_agent_clear_fields(void)
60 g_byte_array_free(agent.ssid, TRUE);
62 g_free(agent.identity);
63 g_free(agent.passphrase);
64 g_free(agent.wps_pin);
68 agent.identity = NULL;
69 agent.passphrase = NULL;
71 agent.wps_pbc = FALSE;
74 int connman_register_agent(void)
76 GVariant *reply = NULL;
77 GVariant *params = NULL;
79 GDBusConnection *connection = NULL;
81 connection = netdbus_get_connection();
82 if (connection == NULL) {
83 ERR("GDBusconnection is NULL");
89 params = g_variant_new("(o)", NETCONFIG_WIFI_PATH);
91 reply = g_dbus_connection_call_sync(
95 CONNMAN_MANAGER_INTERFACE,
99 G_DBUS_CALL_FLAGS_NONE,
101 netdbus_get_cancellable(),
106 if (g_strcmp0(error->message,
107 "GDBus.Error:net.connman.Error.AlreadyExists: Already exists") == 0) {
110 ERR("Fail to register agent [%d: %s]",
111 error->code, error->message);
116 ERR("Fail to register agent");
118 g_variant_unref(reply);
123 INFO("Registered to connman agent successfully");
128 int connman_unregister_agent(void)
130 gboolean reply = FALSE;
131 GVariant *param = NULL;
132 const char *path = NETCONFIG_WIFI_PATH;
134 param = g_variant_new("(o)", path);
136 DBG("ConnMan agent unregister");
138 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
139 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
140 "UnregisterAgent", param, NULL);
143 ERR("Fail to unregister agent");
145 /* Clearing the agent fields */
146 __netconfig_agent_clear_fields();
151 gboolean netconfig_wifi_set_agent_field_for_eap_network(
152 const char *name, const char *identity, const char *passphrase)
159 __netconfig_agent_clear_fields();
161 name_len = strlen(name);
162 agent.ssid = g_byte_array_sized_new(name_len);
163 agent.ssid->len = name_len;
164 memcpy(agent.ssid->data, name, name_len);
167 agent.identity = g_strdup(identity);
170 agent.passphrase = g_strdup(passphrase);
172 DBG("Successfully configured for EAP network");
177 gboolean handle_set_field(NetConnmanAgent *connman_agent,
178 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
180 GError *error = NULL;
184 gboolean updated = FALSE;
185 gboolean reply = FALSE;
187 g_return_val_if_fail(connman_agent != NULL, FALSE);
189 DBG("Set agent fields for %s", service);
191 if (netconfig_is_wifi_profile(service) != TRUE) {
192 error = g_error_new(G_DBUS_ERROR,
193 G_DBUS_ERROR_AUTH_FAILED,
194 CONNMAN_ERROR_INTERFACE ".InvalidService");
196 g_dbus_method_invocation_return_gerror(context, error);
197 g_clear_error(&error);
202 __netconfig_agent_clear_fields();
203 g_variant_get(fields, "a{sv}", &iter);
204 while (g_variant_iter_loop(iter, "{sv}", &field, &value)) {
205 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0) {
206 g_free(agent.passphrase);
207 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
208 agent.passphrase = g_strdup(g_variant_get_string(value, NULL));
211 DBG("Field [%s] - []", field);
213 agent.passphrase = NULL;
215 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PBC) == 0) {
216 agent.wps_pbc = FALSE;
217 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) &&
218 g_strcmp0(g_variant_get_string(value, NULL), "enable") == 0) {
219 agent.wps_pbc = TRUE;
222 DBG("Field [%s] - [%d]", field, agent.wps_pbc);
224 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PIN) == 0) {
225 g_free(agent.wps_pin);
226 agent.wps_pbc = FALSE;
227 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
228 agent.wps_pin = g_strdup(g_variant_get_string(value, NULL));
231 DBG("Field [%s] - []", field);
233 agent.wps_pin = NULL;
235 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0) {
237 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
238 agent.name = g_strdup(g_variant_get_string(value, NULL));
241 DBG("Field [%s] - []", field);
245 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0) {
246 if (agent.ssid != NULL) {
247 g_byte_array_free(agent.ssid, TRUE);
251 if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) {
254 GByteArray *array = g_byte_array_new();
256 g_variant_get(value, "ay", &iter1);
257 while(g_variant_iter_loop(iter1, "y", &char_value)) {
258 g_byte_array_append(array, &char_value, 1);
260 g_variant_iter_free(iter1);
261 if (array != NULL && (array->len > 0)) {
262 agent.ssid = g_byte_array_sized_new(array->len);
263 agent.ssid->len = array->len;
264 memcpy(agent.ssid->data, array->data, array->len);
267 DBG("Field [%s] - []", field);
270 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0) {
271 g_free(agent.identity);
272 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
273 agent.identity = g_strdup(g_variant_get_string(value, NULL));
276 DBG("Field [%s] - []", field);
278 agent.identity = NULL;
283 if (updated == TRUE) {
284 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
285 service, CONNMAN_SERVICE_INTERFACE, "Connect",
286 NULL, __netconfig_wifi_connect_reply);
288 g_dbus_method_invocation_return_value (context, NULL);
290 error = g_error_new(G_DBUS_ERROR,
291 G_DBUS_ERROR_AUTH_FAILED,
292 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
294 g_dbus_method_invocation_return_gerror(context, error);
295 g_clear_error(&error);
298 error = g_error_new(G_DBUS_ERROR,
299 G_DBUS_ERROR_AUTH_FAILED,
300 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
302 g_dbus_method_invocation_return_gerror(context, error);
303 g_clear_error(&error);
307 ERR("Fail to connect Wi-Fi");
309 __netconfig_agent_clear_fields();
311 g_variant_iter_free(iter);
313 net_connman_agent_complete_set_field(connman_agent, context);
317 gboolean handle_request_input(NetConnmanAgent *connman_agent,
318 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
322 GVariant *r_value = NULL;
323 GVariant *out_table = NULL;
324 gboolean updated = FALSE;
325 GVariantBuilder *builder = NULL;
327 g_return_val_if_fail(connman_agent != NULL, FALSE);
332 DBG("Agent fields requested for service: %s", service);
334 builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
336 g_variant_get(fields, "a{sv}", &iter);
337 while (g_variant_iter_loop(iter, "{sv}", &field, &r_value)) {
339 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0 &&
340 agent.passphrase != NULL) {
341 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSPHRASE,
342 g_variant_new_string(agent.passphrase));
345 DBG("Setting [%s] - []", field);
346 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS) == 0 &&
347 (agent.wps_pbc == TRUE || agent.wps_pin != NULL)) {
348 if (agent.wps_pbc == TRUE) {
349 // Sending empty string for WPS push button method
350 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(""));
353 DBG("Setting empty string for [%s]", field);
354 } else if (agent.wps_pin != NULL) {
355 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(agent.wps_pin));
358 DBG("Setting string [%s] - []", field);
360 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0 &&
361 agent.name != NULL) {
362 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_NAME, g_variant_new_string(agent.name));
365 DBG("Settings [%s] - []", field);
366 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0 &&
367 agent.ssid != NULL) {
369 GVariantBuilder *builder1 = NULL;
370 builder1 = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
372 for (i = 0; i < (agent.ssid->len); i++) {
373 g_variant_builder_add (builder1, "y", agent.ssid->data[i]);
376 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_SSID, g_variant_builder_end(builder1));
377 if (builder1 != NULL)
378 g_variant_builder_unref(builder1);
381 DBG("Settings [%s] - []", field);
382 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0 &&
383 agent.identity != NULL) {
384 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_IDENTITY, g_variant_new_string(agent.identity));
387 DBG("Settings [%s] - []", field);
391 out_table = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
394 g_variant_builder_unref(builder);
396 g_variant_iter_free(iter);
399 if (NULL == out_table){
400 net_connman_agent_complete_request_input(connman_agent, context, out_table);
406 g_dbus_method_invocation_return_value (context, out_table);
408 GError *error = NULL;
409 error = g_error_new(G_DBUS_ERROR,
410 G_DBUS_ERROR_AUTH_FAILED,
411 "net.connman.Agent.Error.Canceled");
413 g_dbus_method_invocation_return_gerror(context, error);
414 g_clear_error(&error);
417 __netconfig_agent_clear_fields();
418 g_variant_unref(out_table);
424 gboolean handle_report_error(NetConnmanAgent *connman_agent,
425 GDBusMethodInvocation *context, const gchar *service, const gchar *error)
429 g_return_val_if_fail(connman_agent != NULL, FALSE);
431 net_connman_agent_complete_report_error(connman_agent, context);
432 DBG("Agent error for service[%s] - [%s]", service, error);
434 // Do something when it failed to make a connection
439 #if defined TIZEN_CAPTIVE_PORTAL
440 #if defined TIZEN_WEARABLE
441 #define QUERY_FOR_INTERNET_INTERVAL 2
442 #define TIMER_THRESHOLD 4
444 #define QUERY_FOR_INTERNET_INTERVAL 20
445 #define TIMER_THRESHOLD 120
448 static gboolean is_monitor_notifier_registered = FALSE;
450 #if defined TIZEN_WEARABLE
451 static gboolean is_portal_msg_shown = FALSE;
452 static guint portal_msg_timer = 0;
455 struct poll_timer_data {
461 static struct poll_timer_data timer_data =
462 {QUERY_FOR_INTERNET_INTERVAL, 0, NULL};
464 static gboolean __check_ignore_portal_list(const char * ssid)
468 int ignore_ap_count = 0;
473 DBG("checking ssid [%s]", ssid);
475 DBG("csc string [%s]", def_str);
476 gchar ** ignore_ap_list = g_strsplit(def_str, ",", 0);
477 ignore_ap_count = g_strv_length(ignore_ap_list);
478 for(i = 0; i < ignore_ap_count; i++) {
479 DBG("[%d] - [%s]", i, ignore_ap_list[i]);
480 if (strncmp(ignore_ap_list[i], ssid, strlen(ssid)) == 0) {
481 g_strfreev(ignore_ap_list);
486 g_strfreev(ignore_ap_list);
490 static void __wifi_state_monitor(wifi_service_state_e state,
493 static wifi_state_notifier wifi_state_monitor_notifier = {
494 .wifi_state_changed = __wifi_state_monitor,
498 static void __wifi_state_monitor(wifi_service_state_e state,
501 DBG("Wi-Fi state: %x", state);
503 if (state == NETCONFIG_WIFI_CONNECTED)
506 if (is_monitor_notifier_registered == TRUE) {
507 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
508 is_monitor_notifier_registered = FALSE;
511 #if defined TIZEN_WEARABLE
512 is_portal_msg_shown = FALSE;
515 /* suspend if Internet check activity in progress */
516 if (timer_data.timer_id == 0)
519 netconfig_stop_timer(&timer_data.timer_id);
520 netconfig_stop_internet_check();
522 DBG("Stopped Internet accessibility check");
525 static gboolean __netconfig_wifi_portal_login_timeout(gpointer data)
527 char *service_profile = NULL;
528 GVariant *reply = NULL;
532 struct poll_timer_data *timer = (struct poll_timer_data *)data;
536 if (TRUE == netconfig_get_internet_status()) {
537 if (is_monitor_notifier_registered == TRUE) {
538 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
539 is_monitor_notifier_registered = FALSE;
542 DBG("Portal logged in successfully and update ConnMan state");
543 return FALSE; /* to stop the timer */
545 if (timer->time_elapsed >= TIMER_THRESHOLD) {
546 DBG("Login failed, update ConnMan");
548 if (is_monitor_notifier_registered == TRUE) {
549 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
550 is_monitor_notifier_registered = FALSE;
553 /* Disconnect and forget the AP */
554 service_profile = (char*) netconfig_get_default_profile();
555 if (service_profile && netconfig_is_wifi_profile(service_profile)) {
556 /* Now forget the AP*/
557 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
558 service_profile, CONNMAN_SERVICE_INTERFACE, "Remove",
562 g_variant_unref(reply);
564 ERR("Failed to forget the AP ");
567 if (NETCONFIG_WIFI_CONNECTED ==
568 wifi_state_get_service_state()) {
569 /* check Internet availability by sending and receiving data*/
570 netconfig_check_internet_accessibility();
571 /* Returning TRUE itself is enough to restart the timer */
572 timer->time_elapsed = timer->time_elapsed +
573 QUERY_FOR_INTERNET_INTERVAL;
582 #if defined TIZEN_WEARABLE
583 static gboolean __netconfig_display_portal_msg(gpointer data)
586 wc_launch_popup(WC_POPUP_TYPE_CAPTIVE_PORTAL);
588 netconfig_stop_timer(&portal_msg_timer);
594 static void __netconfig_wifi_portal_login_timer_start(struct poll_timer_data
597 DBG("__netconfig_wifi_browser_start_timer...starting timer");
602 netconfig_stop_timer(&(data->timer_id));
604 /* Timer logic: After successful launch of browser, we would check for
605 * Internet status for every 20s until a threshold of 120s
608 data->time_elapsed = QUERY_FOR_INTERNET_INTERVAL;
609 netconfig_start_timer_seconds(QUERY_FOR_INTERNET_INTERVAL,
610 __netconfig_wifi_portal_login_timeout, data, &(data->timer_id));
614 gboolean handle_request_browser(NetConnmanAgent *connman_agent,
615 GDBusMethodInvocation *context, const gchar *service, const gchar *url)
617 #if defined TIZEN_CAPTIVE_PORTAL
618 gboolean ret = FALSE;
619 gboolean ignore_portal = FALSE;
620 const char * ssid = NULL;
622 g_return_val_if_fail(connman_agent != NULL, FALSE);
624 DBG("service[%s] - url[%s]", service, url);
626 ssid = netconfig_wifi_get_connected_essid(netconfig_get_default_profile());
628 ERR("Connected AP name is NULL!!");
629 net_connman_agent_complete_request_browser(connman_agent, context);
633 ignore_portal = __check_ignore_portal_list(ssid);
635 if (ignore_portal == TRUE){
636 net_connman_agent_complete_request_browser(connman_agent, context);
639 /* Register for Wifi state change notifier*/
640 if (is_monitor_notifier_registered == FALSE) {
641 wifi_state_notifier_register(&wifi_state_monitor_notifier);
642 is_monitor_notifier_registered = TRUE;
645 #if defined TIZEN_WEARABLE
646 if (is_portal_msg_shown){
647 net_connman_agent_complete_request_browser(connman_agent, context);
651 is_portal_msg_shown = TRUE;
652 netconfig_start_timer_seconds(4, __netconfig_display_portal_msg, NULL, &portal_msg_timer);
654 ret = netconfig_send_notification_to_net_popup(NETCONFIG_ADD_PORTAL_NOTI, ssid);
657 timer_data.time_elapsed = 0;
658 __netconfig_wifi_portal_login_timer_start(&timer_data);
660 net_connman_agent_complete_request_browser(connman_agent, context);
663 GError *error = NULL;
664 error = g_error_new(G_DBUS_ERROR,
665 G_DBUS_ERROR_AUTH_FAILED,
666 CONNMAN_ERROR_INTERFACE ".NotSupported");
668 g_dbus_method_invocation_return_gerror(context, error);
669 g_clear_error(&error);