Merge "Add dbus method for getting wifi passphrase" into tizen
[platform/core/connectivity/net-config.git] / src / wifi-agent.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <stdio.h>
21 #include <vconf.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <vconf-keys.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "wifi.h"
29 #include "netdbus.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"
36
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"
47 #endif
48
49 #define NETCONFIG_AGENT_ERR_CONNECT_FAILED              "connect-failed"
50
51 typedef struct {
52         char *interface_name;
53         GByteArray *ssid;
54         char *name;
55         char *identity;
56         char *passphrase;
57         char *wps_pin;
58 #if defined TIZEN_CAPTIVE_PORTAL
59         char *username;
60         char *password;
61 #endif
62         gboolean wps_pbc;
63 } netconfig_wifi_agent_s;
64
65 static GSList *g_agent_list = NULL;
66
67 static void __agent_clear_fields(netconfig_wifi_agent_s *agent)
68 {
69         if (!agent)
70                 return;
71
72         g_free(agent->interface_name);
73         if (agent->ssid)
74                 g_byte_array_free(agent->ssid, TRUE);
75         g_free(agent->name);
76         g_free(agent->identity);
77         g_free(agent->passphrase);
78         g_free(agent->wps_pin);
79 #if defined TIZEN_CAPTIVE_PORTAL
80         g_free(agent->username);
81         g_free(agent->password);
82 #endif
83
84         agent->interface_name = NULL;
85         agent->ssid = NULL;
86         agent->name = NULL;
87         agent->identity = NULL;
88         agent->passphrase = NULL;
89         agent->wps_pin = NULL;
90 #if defined TIZEN_CAPTIVE_PORTAL
91         agent->username = NULL;
92         agent->password = NULL;
93 #endif
94         agent->wps_pbc = FALSE;
95 }
96
97 static void __agent_free_data(gpointer data)
98 {
99         netconfig_wifi_agent_s *agent = data;
100
101         __agent_clear_fields(agent);
102         g_free(agent);
103 }
104
105 static netconfig_wifi_agent_s *__agent_get_data(const char *interface_name)
106 {
107         GSList *list = NULL;
108
109         for (list = g_agent_list; list; list = list->next) {
110                 netconfig_wifi_agent_s *wifi_agent = list->data;
111                 if (g_strcmp0(wifi_agent->interface_name, interface_name) == 0)
112                         return wifi_agent;
113         }
114
115         return NULL;
116 }
117
118 int connman_register_agent(void)
119 {
120         GVariant *reply = NULL;
121         GVariant *params = NULL;
122
123         params = g_variant_new("(o)", NETCONFIG_WIFI_PATH);
124         reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
125                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
126                         "RegisterAgent", params);
127
128         if (reply == NULL) {
129                         ERR("Fail to register agent");
130                         return FALSE;
131         } else
132                 g_variant_unref(reply);
133
134         INFO("Registered to connman agent successfully");
135
136         return TRUE;
137 }
138
139 int connman_unregister_agent(void)
140 {
141         gboolean reply = FALSE;
142         GVariant *param = NULL;
143         const char *path = NETCONFIG_WIFI_PATH;
144
145         param = g_variant_new("(o)", path);
146
147         DBG("ConnMan agent unregister");
148
149         reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
150                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
151                         "UnregisterAgent", param, NULL, NULL);
152
153         if (reply != TRUE)
154                 ERR("Fail to unregister agent");
155
156         /* Clearing the agent fields */
157         g_slist_free_full(g_agent_list, __agent_free_data);
158
159         return reply;
160 }
161
162 gboolean netconfig_wifi_set_agent_field_for_eap_network(const char *interface_name,
163                         const char *name, const char *identity, const char *passphrase)
164 {
165         int name_len;
166         netconfig_wifi_agent_s *wifi_agent = NULL;
167
168         if (name == NULL)
169                 return FALSE;
170
171         wifi_agent = __agent_get_data(interface_name);
172         if (wifi_agent == NULL)
173                 return FALSE;
174
175         __agent_clear_fields(wifi_agent);
176
177         name_len = strlen(name);
178         wifi_agent->ssid = g_byte_array_sized_new(name_len);
179         wifi_agent->ssid->len = name_len;
180         memcpy(wifi_agent->ssid->data, name, name_len + 1);
181
182         if (identity)
183                 wifi_agent->identity = g_strdup(identity);
184
185         if (passphrase)
186                 wifi_agent->passphrase = g_strdup(passphrase);
187
188         gchar *enc_data = NULL;
189         enc_data = _netconfig_encrypt_passphrase(wifi_agent->passphrase);
190
191         if (!enc_data) {
192                 ERR("Failed to encrypt the passphrase");
193         } else {
194                 g_free(wifi_agent->passphrase);
195                 wifi_agent->passphrase = enc_data;
196         }
197
198         DBG("Successfully configured for EAP network");
199
200         return TRUE;
201 }
202
203 gboolean handle_set_field(NetConnmanAgent *connman_agent,
204                 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
205 {
206         GError *error = NULL;
207         GVariantIter *iter;
208         gpointer field;
209         GVariant *value;
210         gboolean updated = FALSE;
211         gboolean reply = FALSE;
212         const char *interface_name = NULL;
213         netconfig_wifi_agent_s *wifi_agent = NULL;
214
215         g_return_val_if_fail(connman_agent != NULL, TRUE);
216
217         DBG("Set agent fields for %s", service);
218
219         if (netconfig_is_wifi_profile(service) != TRUE) {
220                 error = g_error_new(G_DBUS_ERROR,
221                                 G_DBUS_ERROR_AUTH_FAILED,
222                                 CONNMAN_ERROR_INTERFACE ".InvalidService");
223
224                 g_dbus_method_invocation_return_gerror(context, error);
225                 g_clear_error(&error);
226
227                 return TRUE;
228         }
229
230         interface_name = netconfig_get_ifname(service);
231         if (interface_name == NULL) {
232                 error = g_error_new(G_DBUS_ERROR,
233                                 G_DBUS_ERROR_AUTH_FAILED,
234                                 CONNMAN_ERROR_INTERFACE ".InvalidService");
235
236                 g_dbus_method_invocation_return_gerror(context, error);
237                 g_clear_error(&error);
238
239                 return TRUE;
240         }
241
242         wifi_agent = __agent_get_data(interface_name);
243         if (wifi_agent == NULL) {
244                 wifi_agent = g_try_malloc0(sizeof(netconfig_wifi_agent_s));
245                 if (wifi_agent == NULL) {
246                         error = g_error_new(G_DBUS_ERROR,
247                                         G_DBUS_ERROR_AUTH_FAILED,
248                                         CONNMAN_ERROR_INTERFACE ".OutOfMemory");
249
250                         g_dbus_method_invocation_return_gerror(context, error);
251                         g_clear_error(&error);
252
253                         return TRUE;
254                 }
255
256                 g_agent_list = g_slist_append(g_agent_list, wifi_agent);
257         }
258
259         __agent_clear_fields(wifi_agent);
260         wifi_agent->interface_name = g_strdup(interface_name);
261
262         g_variant_get(fields, "a{sv}", &iter);
263         while (g_variant_iter_loop(iter, "{sv}", &field, &value)) {
264                 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0) {
265                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
266                                 wifi_agent->passphrase = g_strdup(g_variant_get_string(value, NULL));
267                                 updated = TRUE;
268
269                                 DBG("Field [%s] - []", (gchar *)field);
270
271                                 if (wifi_agent->passphrase == NULL)
272                                         continue;
273
274                                 if (netconfig_check_passphrase(service, wifi_agent->passphrase) == FALSE) {
275                                         ERR("Invalid passphrase");
276
277                                         g_free(wifi_agent->passphrase);
278                                         wifi_agent->passphrase = NULL;
279
280                                         updated = FALSE;
281                                         continue;
282                                 }
283
284                                 gchar *enc_data = NULL;
285                                 enc_data = _netconfig_encrypt_passphrase(wifi_agent->passphrase);
286
287                                 if (!enc_data) {
288                                         ERR("Failed to encrypt the passphrase");
289                                         continue;
290                                 }
291
292                                 g_free(wifi_agent->passphrase);
293                                 wifi_agent->passphrase = enc_data;
294                         }
295                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PBC) == 0) {
296                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) &&
297                                         g_strcmp0(g_variant_get_string(value, NULL), "enable") == 0) {
298                                 wifi_agent->wps_pbc = TRUE;
299                                 updated = TRUE;
300
301                                 DBG("Field [%s] - [%d]", (gchar *)field, wifi_agent->wps_pbc);
302                         }
303                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS_PIN) == 0) {
304                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
305                                 wifi_agent->wps_pin = g_strdup(g_variant_get_string(value, NULL));
306                                 updated = TRUE;
307
308                                 DBG("Field [%s] - [%s]", (gchar *)field, wifi_agent->wps_pin);
309                         }
310                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0) {
311                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
312                                 wifi_agent->name = g_strdup(g_variant_get_string(value, NULL));
313                                 updated = TRUE;
314
315                                 DBG("Field [%s] - [%s]", (gchar *)field, wifi_agent->name);
316                         }
317                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0) {
318                         if (wifi_agent->ssid != NULL) {
319                                 g_byte_array_free(wifi_agent->ssid, TRUE);
320                                 wifi_agent->ssid = NULL;
321                         }
322
323                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) {
324                                 guint8 char_value;
325                                 GVariantIter *iter1;
326                                 GByteArray *array = g_byte_array_new();
327
328                                 g_variant_get(value, "ay", &iter1);
329                                 while (g_variant_iter_loop(iter1, "y", &char_value))
330                                         g_byte_array_append(array, &char_value, 1);
331                                 g_variant_iter_free(iter1);
332                                 if (array != NULL && (array->len > 0)) {
333                                         wifi_agent->ssid = g_byte_array_sized_new(array->len);
334                                         wifi_agent->ssid->len = array->len;
335                                         memcpy(wifi_agent->ssid->data, array->data, array->len);
336                                         updated = TRUE;
337
338                                         DBG("Field [%s] - []", (gchar *)field);
339                                 }
340                         }
341                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0) {
342                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
343                                 wifi_agent->identity = g_strdup(g_variant_get_string(value, NULL));
344                                 updated = TRUE;
345
346                                 DBG("Field [%s] - [%s]", (gchar *)field, wifi_agent->identity);
347                         }
348 #if defined TIZEN_CAPTIVE_PORTAL
349                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_USERNAME) == 0) {
350                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
351                                 wifi_agent->username = g_strdup(g_variant_get_string(value, NULL));
352                                 updated = TRUE;
353
354                                 DBG("Field [%s] - [%s]", (gchar *)field, wifi_agent->username);
355                         }
356                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSWORD) == 0) {
357                         if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
358                                 wifi_agent->password = g_strdup(g_variant_get_string(value, NULL));
359                                 updated = TRUE;
360
361                                 DBG("Field [%s] - [%s]", (gchar *)field, wifi_agent->password);
362                         }
363 #endif
364                 }
365         }
366
367         g_variant_iter_free(iter);
368
369         if (updated == TRUE) {
370                 reply = netconfig_invoke_dbus_method_nonblock(CONNMAN_SERVICE,
371                                 service, CONNMAN_SERVICE_INTERFACE, "Connect",
372                                 NULL, __netconfig_wifi_connect_reply,
373                                 g_strdup(interface_name));
374                 if (reply != TRUE) {
375                         ERR("Fail to connect Wi-Fi");
376                         __agent_clear_fields(wifi_agent);
377                         error = g_error_new(G_DBUS_ERROR,
378                                         G_DBUS_ERROR_AUTH_FAILED,
379                                         CONNMAN_ERROR_INTERFACE ".InvalidArguments");
380
381                         g_dbus_method_invocation_return_gerror(context, error);
382                         g_clear_error(&error);
383                         return TRUE;
384                 }
385         } else {
386                 ERR("Fail to connect Wi-Fi");
387                 __agent_clear_fields(wifi_agent);
388
389                 error = g_error_new(G_DBUS_ERROR,
390                                 G_DBUS_ERROR_AUTH_FAILED,
391                                 CONNMAN_ERROR_INTERFACE ".InvalidArguments");
392
393                 g_dbus_method_invocation_return_gerror(context, error);
394                 g_clear_error(&error);
395                 return TRUE;
396         }
397
398         net_connman_agent_complete_set_field(connman_agent, context);
399         return TRUE;
400 }
401
402 gboolean handle_request_input(NetConnmanAgent *connman_agent,
403                 GDBusMethodInvocation *context, const gchar *service, GVariant *fields)
404 {
405         GVariantIter *iter;
406         gchar *field = NULL;
407         GVariant *r_value = NULL;
408         GVariant *out_table = NULL;
409         gboolean updated = FALSE;
410         GVariantBuilder *builder = NULL;
411         GError *error = NULL;
412         const char *interface_name = NULL;
413         netconfig_wifi_agent_s *wifi_agent = NULL;
414
415         g_return_val_if_fail(connman_agent != NULL, TRUE);
416
417         if (NULL == service)
418                 return TRUE;
419
420         DBG("Agent fields requested for service: %s", service);
421
422         interface_name = netconfig_get_ifname(service);
423         if (interface_name == NULL) {
424                 error = g_error_new(G_DBUS_ERROR,
425                                 G_DBUS_ERROR_AUTH_FAILED,
426                                 CONNMAN_ERROR_INTERFACE ".InvalidService");
427
428                 g_dbus_method_invocation_return_gerror(context, error);
429                 g_clear_error(&error);
430
431                 return TRUE;
432         }
433
434         wifi_agent = __agent_get_data(interface_name);
435         if (wifi_agent == NULL) {
436                 error = g_error_new(G_DBUS_ERROR,
437                                 G_DBUS_ERROR_AUTH_FAILED,
438                                 CONNMAN_ERROR_INTERFACE ".InvalidService");
439
440                 g_dbus_method_invocation_return_gerror(context, error);
441                 g_clear_error(&error);
442
443                 return TRUE;
444         }
445
446         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
447
448         g_variant_get(fields, "a{sv}", &iter);
449         while (g_variant_iter_loop(iter, "{sv}", &field, &r_value)) {
450
451                 if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSPHRASE) == 0 &&
452                                 wifi_agent->passphrase != NULL) {
453                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSPHRASE,
454                                                         g_variant_new_string(wifi_agent->passphrase));
455
456                         updated = TRUE;
457                         DBG("Setting [%s] - [%s]", field, wifi_agent->passphrase);
458                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_WPS) == 0 &&
459                                 (wifi_agent->wps_pbc == TRUE || wifi_agent->wps_pin != NULL)) {
460                         if (wifi_agent->wps_pbc == TRUE) {
461                                 /* Sending empty string for WPS push button method */
462                                 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS,
463                                         g_variant_new_string(""));
464
465                                 updated = TRUE;
466                                 DBG("Setting empty string for [%s]", field);
467                         } else if (wifi_agent->wps_pin != NULL) {
468                                 g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_WPS,
469                                         g_variant_new_string(wifi_agent->wps_pin));
470
471                                 updated = TRUE;
472                                 DBG("Setting string [%s] - [%s]", field, wifi_agent->wps_pin);
473                         }
474                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_NAME) == 0 &&
475                                 wifi_agent->name != NULL) {
476                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_NAME,
477                                 g_variant_new_string(wifi_agent->name));
478
479                         updated = TRUE;
480                         DBG("Settings [%s] - [%s]", field, wifi_agent->name);
481                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_SSID) == 0 &&
482                                 wifi_agent->ssid != NULL) {
483                         int i = 0;
484                         GVariantBuilder *builder1 = NULL;
485                         builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
486
487                         for (i = 0; i < (wifi_agent->ssid->len); i++)
488                                 g_variant_builder_add(builder1, "y", wifi_agent->ssid->data[i]);
489
490                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_SSID,
491                                         g_variant_builder_end(builder1));
492
493                         g_variant_builder_unref(builder1);
494
495                         updated = TRUE;
496                         DBG("Settings [%s] - []", field);
497                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_IDENTITY) == 0 &&
498                                 wifi_agent->identity != NULL) {
499                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_IDENTITY,
500                                 g_variant_new_string(wifi_agent->identity));
501
502                         updated = TRUE;
503                         DBG("Settings [%s] - [%s]", field, wifi_agent->identity);
504 #if defined TIZEN_CAPTIVE_PORTAL
505                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_USERNAME) == 0 &&
506                                 wifi_agent->username != NULL) {
507                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_USERNAME,
508                                 g_variant_new_string(wifi_agent->username));
509
510                         updated = TRUE;
511                         DBG("Settings [%s] - [%s]", field, wifi_agent->username);
512                 } else if (g_strcmp0(field, NETCONFIG_AGENT_FIELD_PASSWORD) == 0 &&
513                                 wifi_agent->password != NULL) {
514                         g_variant_builder_add(builder, "{sv}", NETCONFIG_AGENT_FIELD_PASSWORD,
515                                 g_variant_new_string(wifi_agent->password));
516
517                         updated = TRUE;
518                         DBG("Settings [%s] - [%s]", field, wifi_agent->password);
519 #endif
520                 }
521         }
522
523         out_table = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
524
525         g_variant_builder_unref(builder);
526
527         g_variant_iter_free(iter);
528
529
530         if (NULL == out_table) {
531                 net_connman_agent_complete_request_input(connman_agent, context, out_table);
532
533                 return TRUE;
534         }
535
536         if (updated == TRUE)
537                 g_dbus_method_invocation_return_value(context, out_table);
538         else {
539                 GError *error = NULL;
540                 error = g_error_new(G_DBUS_ERROR,
541                                 G_DBUS_ERROR_AUTH_FAILED,
542                                 "net.connman.Agent.Error.Canceled");
543
544                 g_dbus_method_invocation_return_gerror(context, error);
545                 g_clear_error(&error);
546         }
547
548         __agent_clear_fields(wifi_agent);
549
550         return TRUE;
551 }
552
553
554 gboolean handle_report_error(NetConnmanAgent *connman_agent,
555                 GDBusMethodInvocation *context, const gchar *service, const gchar *error)
556 {
557         g_return_val_if_fail(connman_agent != NULL, TRUE);
558
559         net_connman_agent_complete_report_error(connman_agent, context);
560         DBG("Agent error for service[%s] - [%s]", service, error);
561
562         /* Do something when it failed to make a connection */
563
564         return TRUE;
565 }
566
567 #if defined TIZEN_CAPTIVE_PORTAL
568 #if defined TIZEN_WEARABLE
569 #define QUERY_FOR_INTERNET_INTERVAL                     2
570 #define TIMER_THRESHOLD                                         4
571 #else
572 #define QUERY_FOR_INTERNET_INTERVAL                     20
573 #define TIMER_THRESHOLD                                         120
574 #endif
575
576 static gboolean is_monitor_notifier_registered = FALSE;
577
578 #if defined TIZEN_WEARABLE
579 static gboolean is_portal_msg_shown = FALSE;
580 #endif
581
582 struct poll_timer_data {
583         guint time_elapsed;
584         guint timer_id;
585         void* data;
586 };
587
588 static struct poll_timer_data timer_data = {
589                 QUERY_FOR_INTERNET_INTERVAL, 0, NULL};
590
591 static gboolean __check_ignore_portal_list(const char * ssid)
592 {
593         char def_str[1024];
594         int i = 0;
595         int ignore_ap_count = 0;
596
597         if (ssid == NULL)
598                 return FALSE;
599
600         DBG("checking ssid [%s]", ssid);
601
602         DBG("csc string [%s]", def_str);
603         gchar ** ignore_ap_list = g_strsplit(def_str, ",", 0);
604         ignore_ap_count = g_strv_length(ignore_ap_list);
605         for (i = 0; i < ignore_ap_count; i++) {
606                 DBG("[%d] - [%s]", i, ignore_ap_list[i]);
607                 if (strncmp(ignore_ap_list[i], ssid, strlen(ssid)) == 0) {
608                         g_strfreev(ignore_ap_list);
609                         return TRUE;
610                 }
611         }
612
613         g_strfreev(ignore_ap_list);
614         return FALSE;
615 }
616
617 static void __wifi_state_monitor(wifi_state_notifier_s *notifier,
618                 char *service, wifi_service_state_e state, void *user_data);
619
620 static wifi_state_notifier_s wifi_state_monitor_notifier = {
621                 .notifier = NULL,
622                 .service = NULL,
623                 .wifi_state_changed = __wifi_state_monitor,
624                 .user_data = NULL,
625 };
626
627 static void __wifi_state_monitor(wifi_state_notifier_s *notifier,
628                 char *service, wifi_service_state_e state, void *user_data)
629 {
630         DBG("Wi-Fi state: %x", state);
631
632         if (state == NETCONFIG_WIFI_CONNECTED)
633                 return;
634
635         if (is_monitor_notifier_registered == TRUE) {
636                 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
637                 is_monitor_notifier_registered = FALSE;
638         }
639
640 #if defined TIZEN_WEARABLE
641         is_portal_msg_shown = FALSE;
642 #endif
643
644         /* suspend if Internet check activity in progress */
645         if (timer_data.timer_id == 0)
646                 return;
647
648         netconfig_stop_timer(&timer_data.timer_id);
649         netconfig_stop_internet_check();
650
651         DBG("Stopped Internet accessibility check");
652 }
653
654 static gboolean __netconfig_wifi_portal_login_timeout(gpointer data)
655 {
656         char *service_profile = NULL;
657         GVariant *reply = NULL;
658
659         DBG("");
660
661         struct poll_timer_data *timer = (struct poll_timer_data *)data;
662         if (timer == NULL)
663                 return FALSE;
664
665         if (TRUE == netconfig_get_internet_status()) {
666                 if (is_monitor_notifier_registered == TRUE) {
667                         wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
668                         is_monitor_notifier_registered = FALSE;
669                 }
670
671                 DBG("Portal logged in successfully and update ConnMan state");
672                 return FALSE; /* to stop the timer */
673         } else {
674                 if (timer->time_elapsed >= TIMER_THRESHOLD) {
675                         DBG("Login failed, update ConnMan");
676
677                         if (is_monitor_notifier_registered == TRUE) {
678                                 wifi_state_notifier_unregister(&wifi_state_monitor_notifier);
679                                 is_monitor_notifier_registered = FALSE;
680                         }
681
682                         /* Disconnect and forget the AP */
683                         service_profile = (char *)netconfig_get_default_profile();
684                         if (service_profile && netconfig_is_wifi_profile(service_profile)) {
685                                 /* Now forget the AP*/
686                                 reply = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
687                                                 service_profile, CONNMAN_SERVICE_INTERFACE, "Remove",
688                                                 NULL);
689
690                                 if (reply != NULL)
691                                         g_variant_unref(reply);
692                                 else
693                                         ERR("Failed to forget the AP ");
694                         }
695                 } else {
696                         if (wifi_state_get_service_state(netconfig_get_default_ifname())
697                                         == NETCONFIG_WIFI_CONNECTED) {
698                                 /* check Internet availability by sending and receiving data*/
699                                 netconfig_check_internet_accessibility();
700                                 /* Returning TRUE itself is enough to restart the timer */
701                                 timer->time_elapsed = timer->time_elapsed +
702                                                                         QUERY_FOR_INTERNET_INTERVAL;
703                                 return TRUE;
704                         }
705                 }
706         }
707
708         return FALSE;
709 }
710
711 static void __netconfig_wifi_portal_login_timer_start(struct poll_timer_data
712                 *data)
713 {
714         DBG("__netconfig_wifi_browser_start_timer...starting timer");
715
716         if (data == NULL)
717                 return;
718
719         netconfig_stop_timer(&(data->timer_id));
720
721         /* Timer logic: After successful launch of browser, we would check for
722          * Internet status for every 20s until a threshold of 120s
723          */
724
725         data->time_elapsed = QUERY_FOR_INTERNET_INTERVAL;
726         netconfig_start_timer_seconds(QUERY_FOR_INTERNET_INTERVAL,
727                 __netconfig_wifi_portal_login_timeout, data, &(data->timer_id));
728 }
729 #endif
730
731 gboolean handle_request_browser(NetConnmanAgent *connman_agent,
732                 GDBusMethodInvocation *context, const gchar *service, const gchar *url)
733 {
734 #if defined TIZEN_CAPTIVE_PORTAL
735         gboolean ignore_portal = FALSE;
736         const char * ssid = NULL;
737
738         g_return_val_if_fail(connman_agent != NULL, TRUE);
739
740         DBG("service[%s] - url[%s]", service, url);
741
742         ssid = netconfig_wifi_get_connected_essid(netconfig_get_default_profile());
743         if (ssid == NULL) {
744                 ERR("Connected AP name is NULL!!");
745                 net_connman_agent_complete_request_browser(connman_agent, context);
746                 return TRUE;
747         }
748
749         ignore_portal = __check_ignore_portal_list(ssid);
750
751         if (ignore_portal == TRUE) {
752                 net_connman_agent_complete_request_browser(connman_agent, context);
753                 return TRUE;
754         }
755         /* Register for Wifi state change notifier*/
756         if (is_monitor_notifier_registered == FALSE) {
757                 wifi_state_notifier_register(&wifi_state_monitor_notifier);
758                 is_monitor_notifier_registered = TRUE;
759         }
760
761         netconfig_send_notification_to_net_popup(NETCONFIG_ADD_PORTAL_NOTI, ssid);
762
763         timer_data.time_elapsed = 0;
764         __netconfig_wifi_portal_login_timer_start(&timer_data);
765
766         net_connman_agent_complete_request_browser(connman_agent, context);
767         return TRUE;
768 #else
769         GError *error = NULL;
770         error = g_error_new(G_DBUS_ERROR,
771                         G_DBUS_ERROR_AUTH_FAILED,
772                         CONNMAN_ERROR_INTERFACE ".NotSupported");
773
774         g_dbus_method_invocation_return_gerror(context, error);
775         g_clear_error(&error);
776
777         return TRUE;
778 #endif
779 }