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"
36 #define NETCONFIG_AGENT_FIELD_NAME "Name"
37 #define NETCONFIG_AGENT_FIELD_SSID "SSID"
38 #define NETCONFIG_AGENT_FIELD_IDENTITY "Identity"
39 #define NETCONFIG_AGENT_FIELD_PASSPHRASE "Passphrase"
40 #define NETCONFIG_AGENT_FIELD_WPS "WPS"
41 #define NETCONFIG_AGENT_FIELD_WPS_PBC "WPS_PBC"
42 #define NETCONFIG_AGENT_FIELD_WPS_PIN "WPS_PIN"
44 #define NETCONFIG_AGENT_ERR_CONNECT_FAILED "connect-failed"
46 struct netconfig_wifi_agent {
55 static struct netconfig_wifi_agent agent;
57 static void __netconfig_agent_clear_fields(void)
59 g_byte_array_free(agent.ssid, TRUE);
61 g_free(agent.identity);
62 g_free(agent.passphrase);
63 g_free(agent.wps_pin);
67 agent.identity = NULL;
68 agent.passphrase = NULL;
70 agent.wps_pbc = FALSE;
73 int connman_register_agent(void)
75 GVariant *reply = NULL;
76 GVariant *params = NULL;
78 params = g_variant_new("(o)", NETCONFIG_WIFI_PATH);
79 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
80 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
81 "RegisterAgent", params);
84 ERR("Fail to register agent");
87 g_variant_unref(reply);
89 INFO("Registered to connman agent successfully");
94 int connman_unregister_agent(void)
96 gboolean reply = FALSE;
97 GVariant *param = NULL;
98 const char *path = NETCONFIG_WIFI_PATH;
100 param = g_variant_new("(o)", path);
102 DBG("ConnMan agent unregister");
104 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
105 CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
106 "UnregisterAgent", param, NULL);
109 ERR("Fail to unregister agent");
111 /* Clearing the agent fields */
112 __netconfig_agent_clear_fields();
117 gboolean netconfig_wifi_set_agent_field_for_eap_network(
118 const char *name, const char *identity, const char *passphrase)
125 __netconfig_agent_clear_fields();
127 name_len = strlen(name);
128 agent.ssid = g_byte_array_sized_new(name_len);
129 agent.ssid->len = name_len;
130 memcpy(agent.ssid->data, name, name_len + 1);
133 agent.identity = g_strdup(identity);
136 agent.passphrase = g_strdup(passphrase);
138 DBG("Successfully configured for EAP network");
143 gboolean handle_set_field(NetConnmanAgent *connman_agent,
144 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
146 GError *error = NULL;
150 gboolean updated = FALSE;
151 gboolean reply = FALSE;
153 g_return_val_if_fail(connman_agent != NULL, FALSE);
155 DBG("Set agent fields for %s", service);
157 if (netconfig_is_wifi_profile(service) != TRUE) {
158 error = g_error_new(G_DBUS_ERROR,
159 G_DBUS_ERROR_AUTH_FAILED,
160 CONNMAN_ERROR_INTERFACE ".InvalidService");
162 g_dbus_method_invocation_return_gerror(context, error);
163 g_clear_error(&error);
168 __netconfig_agent_clear_fields();
169 g_variant_get(fields, "a{sv}", &iter);
170 while (g_variant_iter_loop(iter, "{sv}", &field, &value)) {
171 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0) {
172 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
173 agent.passphrase = g_strdup(g_variant_get_string(value, NULL));
176 DBG("Field [%s] - []", field);
178 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PBC) == 0) {
179 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) &&
180 g_strcmp0(g_variant_get_string(value, NULL), "enable") == 0) {
181 agent.wps_pbc = TRUE;
184 DBG("Field [%s] - [%d]", field, agent.wps_pbc);
186 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PIN) == 0) {
187 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
188 agent.wps_pin = g_strdup(g_variant_get_string(value, NULL));
191 DBG("Field [%s] - []", field);
193 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0) {
194 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
195 agent.name = g_strdup(g_variant_get_string(value, NULL));
198 DBG("Field [%s] - []", field);
200 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0) {
201 if (agent.ssid != NULL) {
202 g_byte_array_free(agent.ssid, TRUE);
206 if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) {
209 GByteArray *array = g_byte_array_new();
211 g_variant_get(value, "ay", &iter1);
212 while (g_variant_iter_loop(iter1, "y", &char_value))
213 g_byte_array_append(array, &char_value, 1);
214 g_variant_iter_free(iter1);
215 if (array != NULL && (array->len > 0)) {
216 agent.ssid = g_byte_array_sized_new(array->len);
217 agent.ssid->len = array->len;
218 memcpy(agent.ssid->data, array->data, array->len);
221 DBG("Field [%s] - []", field);
224 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0) {
225 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
226 agent.identity = g_strdup(g_variant_get_string(value, NULL));
229 DBG("Field [%s] - []", field);
234 if (updated == TRUE) {
235 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
236 service, CONNMAN_SERVICE_INTERFACE, "Connect",
237 NULL, __netconfig_wifi_connect_reply);
239 g_dbus_method_invocation_return_value(context, NULL);
241 error = g_error_new(G_DBUS_ERROR,
242 G_DBUS_ERROR_AUTH_FAILED,
243 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
245 g_dbus_method_invocation_return_gerror(context, error);
246 g_clear_error(&error);
249 error = g_error_new(G_DBUS_ERROR,
250 G_DBUS_ERROR_AUTH_FAILED,
251 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
253 g_dbus_method_invocation_return_gerror(context, error);
254 g_clear_error(&error);
258 ERR("Fail to connect Wi-Fi");
260 __netconfig_agent_clear_fields();
262 g_variant_iter_free(iter);
264 net_connman_agent_complete_set_field(connman_agent, context);
268 gboolean handle_request_input(NetConnmanAgent *connman_agent,
269 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
273 GVariant *r_value = NULL;
274 GVariant *out_table = NULL;
275 gboolean updated = FALSE;
276 GVariantBuilder *builder = NULL;
278 g_return_val_if_fail(connman_agent != NULL, FALSE);
283 DBG("Agent fields requested for service: %s", service);
285 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
287 g_variant_get(fields, "a{sv}", &iter);
288 while (g_variant_iter_loop(iter, "{sv}", &field, &r_value)) {
290 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0 &&
291 agent.passphrase != NULL) {
292 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSPHRASE,
293 g_variant_new_string(agent.passphrase));
296 DBG("Setting [%s] - []", field);
297 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS) == 0 &&
298 (agent.wps_pbc == TRUE || agent.wps_pin != NULL)) {
299 if (agent.wps_pbc == TRUE) {
300 /* Sending empty string for WPS push button method */
301 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(""));
304 DBG("Setting empty string for [%s]", field);
305 } else if (agent.wps_pin != NULL) {
306 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS, g_variant_new_string(agent.wps_pin));
309 DBG("Setting string [%s] - []", field);
311 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0 &&
312 agent.name != NULL) {
313 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_NAME, g_variant_new_string(agent.name));
316 DBG("Settings [%s] - []", field);
317 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0 &&
318 agent.ssid != NULL) {
320 GVariantBuilder *builder1 = NULL;
321 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
323 for (i = 0; i < (agent.ssid->len); i++)
324 g_variant_builder_add(builder1, "y", agent.ssid->data[i]);
326 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_SSID, g_variant_builder_end(builder1));
327 if (builder1 != NULL)
328 g_variant_builder_unref(builder1);
331 DBG("Settings [%s] - []", field);
332 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0 &&
333 agent.identity != NULL) {
334 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_IDENTITY, g_variant_new_string(agent.identity));
337 DBG("Settings [%s] - []", field);
341 out_table = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
344 g_variant_builder_unref(builder);
346 g_variant_iter_free(iter);
349 if (NULL == out_table) {
350 net_connman_agent_complete_request_input(connman_agent, context, out_table);
356 g_dbus_method_invocation_return_value(context, out_table);
358 GError *error = NULL;
359 error = g_error_new(G_DBUS_ERROR,
360 G_DBUS_ERROR_AUTH_FAILED,
361 "net.connman.Agent.Error.Canceled");
363 g_dbus_method_invocation_return_gerror(context, error);
364 g_clear_error(&error);
367 __netconfig_agent_clear_fields();
368 g_variant_unref(out_table);
374 gboolean handle_report_error(NetConnmanAgent *connman_agent,
375 GDBusMethodInvocation *context, const gchar *service, const gchar *error)
379 g_return_val_if_fail(connman_agent != NULL, FALSE);
381 net_connman_agent_complete_report_error(connman_agent, context);
382 DBG("Agent error for service[%s] - [%s]", service, error);
384 /* Do something when it failed to make a connection */
389 #if defined TIZEN_CAPTIVE_PORTAL
390 #if defined TIZEN_WEARABLE
391 #define QUERY_FOR_INTERNET_INTERVAL 2
392 #define TIMER_THRESHOLD 4
394 #define QUERY_FOR_INTERNET_INTERVAL 20
395 #define TIMER_THRESHOLD 120
398 static gboolean is_monitor_notifier_registered = FALSE;
400 #if defined TIZEN_WEARABLE
401 static gboolean is_portal_msg_shown = FALSE;
404 struct poll_timer_data {
410 static struct poll_timer_data timer_data = {
411 QUERY_FOR_INTERNET_INTERVAL, 0, NULL};
413 static gboolean __check_ignore_portal_list(const char * ssid)
417 int ignore_ap_count = 0;
422 DBG("checking ssid [%s]", ssid);
424 DBG("csc string [%s]", def_str);
425 gchar ** ignore_ap_list = g_strsplit(def_str, ",", 0);
426 ignore_ap_count = g_strv_length(ignore_ap_list);
427 for (i = 0; i < ignore_ap_count; i++) {
428 DBG("[%d] - [%s]", i, ignore_ap_list[i]);
429 if (strncmp(ignore_ap_list[i], ssid, strlen(ssid)) == 0) {
430 g_strfreev(ignore_ap_list);
435 g_strfreev(ignore_ap_list);
439 static void __wifi_state_monitor(wifi_service_state_e state,
442 static wifi_state_notifier wifi_state_monitor_notifier = {
443 .wifi_state_changed = __wifi_state_monitor,
447 static void __wifi_state_monitor(wifi_service_state_e state,
450 DBG("Wi-Fi state: %x", state);
452 if (state == NETCONFIG_WIFI_CONNECTED)
455 if (is_monitor_notifier_registered == TRUE) {
456 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
457 is_monitor_notifier_registered = FALSE;
460 #if defined TIZEN_WEARABLE
461 is_portal_msg_shown = FALSE;
464 /* suspend if Internet check activity in progress */
465 if (timer_data.timer_id == 0)
468 netconfig_stop_timer(&timer_data.timer_id);
469 netconfig_stop_internet_check();
471 DBG("Stopped Internet accessibility check");
474 static gboolean __netconfig_wifi_portal_login_timeout(gpointer data)
476 char *service_profile = NULL;
477 GVariant *reply = NULL;
481 struct poll_timer_data *timer = (struct poll_timer_data *)data;
485 if (TRUE == netconfig_get_internet_status()) {
486 if (is_monitor_notifier_registered == TRUE) {
487 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
488 is_monitor_notifier_registered = FALSE;
491 DBG("Portal logged in successfully and update ConnMan state");
492 return FALSE; /* to stop the timer */
494 if (timer->time_elapsed >= TIMER_THRESHOLD) {
495 DBG("Login failed, update ConnMan");
497 if (is_monitor_notifier_registered == TRUE) {
498 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
499 is_monitor_notifier_registered = FALSE;
502 /* Disconnect and forget the AP */
503 service_profile = (char*) netconfig_get_default_profile();
504 if (service_profile && netconfig_is_wifi_profile(service_profile)) {
505 /* Now forget the AP*/
506 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
507 service_profile, CONNMAN_SERVICE_INTERFACE, "Remove",
511 g_variant_unref(reply);
513 ERR("Failed to forget the AP ");
516 if (NETCONFIG_WIFI_CONNECTED ==
517 wifi_state_get_service_state()) {
518 /* check Internet availability by sending and receiving data*/
519 netconfig_check_internet_accessibility();
520 /* Returning TRUE itself is enough to restart the timer */
521 timer->time_elapsed = timer->time_elapsed +
522 QUERY_FOR_INTERNET_INTERVAL;
531 static void __netconfig_wifi_portal_login_timer_start(struct poll_timer_data
534 DBG("__netconfig_wifi_browser_start_timer...starting timer");
539 netconfig_stop_timer(&(data->timer_id));
541 /* Timer logic: After successful launch of browser, we would check for
542 * Internet status for every 20s until a threshold of 120s
545 data->time_elapsed = QUERY_FOR_INTERNET_INTERVAL;
546 netconfig_start_timer_seconds(QUERY_FOR_INTERNET_INTERVAL,
547 __netconfig_wifi_portal_login_timeout, data, &(data->timer_id));
551 gboolean handle_request_browser(NetConnmanAgent *connman_agent,
552 GDBusMethodInvocation *context, const gchar *service, const gchar *url)
554 #if defined TIZEN_CAPTIVE_PORTAL
555 gboolean ret = FALSE;
556 gboolean ignore_portal = FALSE;
557 const char * ssid = NULL;
559 g_return_val_if_fail(connman_agent != NULL, FALSE);
561 DBG("service[%s] - url[%s]", service, url);
563 ssid = netconfig_wifi_get_connected_essid(netconfig_get_default_profile());
565 ERR("Connected AP name is NULL!!");
566 net_connman_agent_complete_request_browser(connman_agent, context);
570 ignore_portal = __check_ignore_portal_list(ssid);
572 if (ignore_portal == TRUE) {
573 net_connman_agent_complete_request_browser(connman_agent, context);
576 /* Register for Wifi state change notifier*/
577 if (is_monitor_notifier_registered == FALSE) {
578 wifi_state_notifier_register(&wifi_state_monitor_notifier);
579 is_monitor_notifier_registered = TRUE;
582 ret = netconfig_send_notification_to_net_popup(NETCONFIG_ADD_PORTAL_NOTI, ssid);
584 timer_data.time_elapsed = 0;
585 __netconfig_wifi_portal_login_timer_start(&timer_data);
587 net_connman_agent_complete_request_browser(connman_agent, context);
590 GError *error = NULL;
591 error = g_error_new(G_DBUS_ERROR,
592 G_DBUS_ERROR_AUTH_FAILED,
593 CONNMAN_ERROR_INTERFACE ".NotSupported");
595 g_dbus_method_invocation_return_gerror(context, error);
596 g_clear_error(&error);