a8588566b81c51b7235ffe92714965566387bee7
[platform/core/connectivity/net-config.git] / src / signal-handler.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 <stdlib.h>
22 #include <string.h>
23 #include <vconf.h>
24 #include <vconf-keys.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "netdbus.h"
29 #include "neterror.h"
30 #include "wifi-wps.h"
31 #include "wifi-bssid-scan.h"
32 #include "wifi-agent.h"
33 #include "wifi-power.h"
34 #include "wifi-state.h"
35 #include "netsupplicant.h"
36 #include "network-state.h"
37 #include "cellular-state.h"
38 #include "signal-handler.h"
39 #include "wifi-background-scan.h"
40 #include "wifi-tdls.h"
41 #include "ip-conflict-detect.h"
42
43 #define DBUS_SERVICE_DBUS                       "org.freedesktop.DBus"
44 #define DBUS_INTERFACE_DBUS                     "org.freedesktop.DBus"
45 #define SIGNAL_INTERFACE_REMOVED                "InterfaceRemoved"
46 #define SIGNAL_SCAN_DONE                        "ScanDone"
47 #define SIGNAL_BSS_ADDED                        "BSSAdded"
48 #define SIGNAL_PROPERTIES_CHANGED               "PropertiesChanged"
49 #define SIGNAL_PROPERTIES_DRIVER_HANGED         "DriverHanged"
50 #define SIGNAL_PROPERTIES_SESSION_OVERLAPPED    "SessionOverlapped"
51 #define SIGNAL_TDLS_CONNECTED                           "TDLSConnected"
52 #define SIGNAL_TDLS_DISCONNECTED                        "TDLSDisconnected"
53 #define SIGNAL_TDLS_PEER_FOUND                          "TDLSPeerFound"
54
55 #define SIGNAL_WPS_CONNECTED                            "WPSConnected"
56 #define SIGNAL_WPS_EVENT                                        "Event"
57 #define SIGNAL_WPS_CREDENTIALS                          "Credentials"
58
59 #define CONNMAN_SIGNAL_SERVICES_CHANGED         "ServicesChanged"
60 #define CONNMAN_SIGNAL_PROPERTY_CHANGED         "PropertyChanged"
61 #define CONNMAN_SIGNAL_NAME_CHANGED             "NameOwnerChanged"
62
63 #define MAX_SIG_LEN 64
64 #define TOTAL_CONN_SIGNALS 5
65 #define MAX_SOCKET_OPEN_RETRY 5
66
67 typedef enum {
68         SIG_INTERFACE_REMOVED = 0,
69         SIG_PROPERTIES_CHANGED,
70         SIG_BSS_ADDED,
71         SIG_SCAN_DONE,
72         SIG_DRIVER_HANGED,
73         SIG_SESSION_OVERLAPPED,
74         SIG_TDLS_CONNECTED,
75         SIG_TDLS_DISCONNECTED,
76         SIG_TDLS_PEER_FOUND,
77         SIG_MAX
78 } SuppSigArrayIndex;
79
80 static int conn_subscription_ids[TOTAL_CONN_SIGNALS] = {0};
81 static const char supplicant_signals[SIG_MAX][MAX_SIG_LEN] = {
82                 SIGNAL_INTERFACE_REMOVED,
83                 SIGNAL_PROPERTIES_CHANGED,
84                 SIGNAL_BSS_ADDED,
85                 SIGNAL_SCAN_DONE,
86                 SIGNAL_PROPERTIES_DRIVER_HANGED,
87                 SIGNAL_PROPERTIES_SESSION_OVERLAPPED,
88                 SIGNAL_TDLS_CONNECTED,
89                 SIGNAL_TDLS_DISCONNECTED,
90                 SIGNAL_TDLS_PEER_FOUND,
91 };
92
93 static int supp_subscription_ids[SIG_MAX] = {0};
94
95 typedef void (*supplicant_signal_cb)(GDBusConnection *conn,
96                 const gchar *name, const gchar *path, const gchar *interface,
97                 const gchar *sig, GVariant *param, gpointer user_data);
98 typedef void (*connman_signal_cb)(GDBusConnection *conn,
99                 const gchar *name, const gchar *path, const gchar *interface,
100                 const gchar *sig, GVariant *param, gpointer user_data);
101
102 static void __netconfig_extract_ipv4_signal_data(GVariant *dictionary, const gchar *profile)
103 {
104         gchar *key = NULL;
105         const gchar *value = NULL;
106         GVariant *var = NULL;
107         GVariantIter iter;
108
109         g_variant_iter_init(&iter, dictionary);
110         while (g_variant_iter_loop(&iter, "{sv}", &key, &var)) {
111                 if (g_strcmp0(key, "Address") == 0)  {
112                         g_variant_get(var, "&s", &value);
113                         char *old_ip = vconf_get_str(VCONFKEY_NETWORK_IP);
114
115                         DBG("Old IPv4.Address [%s] Received new IPv4.Address [%s]", old_ip, value);
116                         if (g_strcmp0(old_ip, value) != 0) {
117                                 if (value != NULL)
118                                         vconf_set_str(VCONFKEY_NETWORK_IP, value);
119                                 else if (old_ip != NULL && strlen(old_ip) > 0)
120                                         vconf_set_str(VCONFKEY_NETWORK_IP, "");
121                         }
122                         free(old_ip);
123                 }
124         }
125 }
126
127 static void __netconfig_extract_ipv6_signal_data(GVariant *dictionary, const gchar *profile)
128 {
129         gchar *key = NULL;
130         const gchar *value = NULL;
131         GVariant *var = NULL;
132         GVariantIter iter;
133
134         g_variant_iter_init(&iter, dictionary);
135         while (g_variant_iter_loop(&iter, "{sv}", &key, &var)) {
136                 if (g_strcmp0(key, "Address") == 0)  {
137                         g_variant_get(var, "&s", &value);
138                         char *old_ip6 = vconf_get_str(VCONFKEY_NETWORK_IP6);
139
140                         DBG("Old IPv6.Address [%s] Received new IPv6.Address [%s]", old_ip6, value);
141                         if (g_strcmp0(old_ip6, value) != 0) {
142                                 if (value != NULL)
143                                         vconf_set_str(VCONFKEY_NETWORK_IP6, value);
144                                 else if (old_ip6 != NULL && strlen(old_ip6) > 0)
145                                         vconf_set_str(VCONFKEY_NETWORK_IP6, "");
146                         }
147                         free(old_ip6);
148                 }
149         }
150 }
151
152 static void _technology_signal_cb(GDBusConnection *conn,
153                 const gchar *name, const gchar *path, const gchar *interface,
154                 const gchar *sig, GVariant *param, gpointer user_data)
155 {
156         gchar *key = NULL;
157         gboolean value = FALSE;
158         GVariant *var = NULL;
159
160         if (param == NULL)
161                 return;
162
163         if (g_str_has_prefix(path, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == TRUE) {
164                 g_variant_get(param, "(sv)", &key, &var);
165                 if (g_strcmp0(key, "Powered") == 0) {
166                         /* Power state */
167                         value = g_variant_get_boolean(var);
168                         if (value == TRUE)
169                                 wifi_state_update_power_state(TRUE);
170                         else
171                                 wifi_state_update_power_state(FALSE);
172                 } else if (g_strcmp0(key, "Connected") == 0) {
173                         /* Connection state */
174                         value = g_variant_get_boolean(var);
175                         if (value == TRUE)
176                                 wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_CONNECTED);
177                         else
178                                 wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_POWERED);
179                 } else if (g_strcmp0(key, "Tethering") == 0) {
180                         /* Tethering state */
181                         wifi_state_set_tech_state(NETCONFIG_WIFI_TECH_TETHERED);
182                 }
183                 if (key)
184                         g_free(key);
185                 if (var)
186                         g_variant_unref(var);
187         }
188 }
189
190 static void _service_signal_cb(GDBusConnection *conn,
191                 const gchar *name, const gchar *path,
192                 const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data)
193 {
194         gchar *sigvalue = NULL;
195         gchar *property;
196         GVariant *variant = NULL, *var;
197         GVariantIter *iter;
198         const gchar *value = NULL;
199         struct sock_data *sd = NULL;
200         int idx = 0;
201
202         if (path == NULL || param == NULL)
203                 goto done;
204
205         g_variant_get(param, "(sv)", &sigvalue, &variant);
206         if (sigvalue == NULL)
207                 goto done;
208
209         if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
210                 goto done;
211
212         if (g_strcmp0(sigvalue, "State") == 0) {
213                 g_variant_get(variant, "s", &property);
214
215         DBG("[%s] %s", property, path);
216         if (netconfig_is_wifi_profile(path) || netconfig_is_ethernet_profile(path)) {
217                 if (g_strcmp0(property, "ready") == 0) {
218                         for (idx = 0; idx < MAX_SOCKET_OPEN_RETRY; idx++) {
219                                 sd = start_ip_conflict_mon();
220                                 if (sd != NULL)
221                                         break;
222                         }
223                 } else if (g_strcmp0(property, "online") == 0) {
224                         // do nothing
225                 } else {
226                         stop_ip_conflict_mon();
227                 }
228         }
229
230                 if (netconfig_is_wifi_profile(path) == TRUE) {
231                         int wifi_state = 0;
232
233                         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
234                         if (wifi_state == VCONFKEY_WIFI_OFF) {
235                                 g_free(property);
236                                 goto done;
237                         }
238
239                         if (g_strcmp0(property, "ready") == 0 || g_strcmp0(property, "online") == 0) {
240                                 if (wifi_state >= VCONFKEY_WIFI_CONNECTED) {
241                                         g_free(property);
242                                         goto done;
243                                 }
244
245                                 netconfig_update_default_profile(path);
246
247                                 wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTED);
248
249                         } else if (g_strcmp0(property, "failure") == 0 || g_strcmp0(property, "disconnect") == 0 || g_strcmp0(property, "idle") == 0) {
250                                 if (netconfig_get_default_profile() == NULL ||
251                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
252                                                 != TRUE) {
253                                         if (g_strcmp0(property, "failure") == 0)
254                                                 wifi_state_set_service_state(NETCONFIG_WIFI_FAILURE);
255                                         else
256                                                 wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
257                                         g_free(property);
258                                         goto done;
259                                 }
260
261                                 if (g_strcmp0(path, netconfig_get_default_profile()) != 0) {
262                                         g_free(property);
263                                         goto done;
264                                 }
265
266                                 netconfig_update_default_profile(NULL);
267
268                                 if (g_strcmp0(property, "failure") == 0)
269                                         wifi_state_set_service_state(NETCONFIG_WIFI_FAILURE);
270                                 else
271                                         wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
272
273                         } else if (g_strcmp0(property, "association") == 0 || g_strcmp0(property, "configuration") == 0) {
274                                 if (netconfig_get_default_profile() == NULL ||
275                                                 netconfig_is_wifi_profile(netconfig_get_default_profile()) != TRUE) {
276                                         if (g_strcmp0(property, "association") == 0)
277                                                 wifi_state_set_service_state(NETCONFIG_WIFI_ASSOCIATION);
278                                         else
279                                                 wifi_state_set_service_state(NETCONFIG_WIFI_CONFIGURATION);
280                                         g_free(property);
281                                         goto done;
282                                 }
283
284                                 if (g_strcmp0(path, netconfig_get_default_profile()) != 0) {
285                                         g_free(property);
286                                         goto done;
287                                 }
288
289                                 netconfig_update_default_profile(NULL);
290
291                                 if (g_strcmp0(property, "association") == 0)
292                                         wifi_state_set_service_state(NETCONFIG_WIFI_ASSOCIATION);
293                                 else
294                                         wifi_state_set_service_state(NETCONFIG_WIFI_CONFIGURATION);
295
296                         }
297                 } else {
298                         if (g_strcmp0(property, "ready") == 0 || g_strcmp0(property, "online") == 0) {
299                                 if (netconfig_get_default_profile() == NULL) {
300                                         if (!netconfig_is_cellular_profile(path))
301                                                 netconfig_update_default_profile(path);
302                                         else {
303                                                 if (netconfig_is_cellular_internet_profile(path))
304                                                         netconfig_update_default_profile(path);
305                                         }
306                                 }
307
308                                 if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path))
309                                         cellular_state_set_service_state(NETCONFIG_CELLULAR_ONLINE);
310
311                         } else if (g_strcmp0(property, "failure") == 0 || g_strcmp0(property, "disconnect") == 0 || g_strcmp0(property, "idle") == 0) {
312                                 if (netconfig_get_default_profile() == NULL) {
313                                         g_free(property);
314                                         goto done;
315                                 }
316
317                                 if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path))
318                                         cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE);
319
320                                 if (g_strcmp0(path, netconfig_get_default_profile()) != 0) {
321                                         g_free(property);
322                                         goto done;
323                                 }
324
325                                 netconfig_update_default_profile(NULL);
326                         } else if (g_strcmp0(property, "association") == 0 || g_strcmp0(property, "configuration") == 0) {
327                                 if (netconfig_get_default_profile() == NULL) {
328                                         g_free(property);
329                                         goto done;
330                                 }
331
332                                 if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path))
333                                         cellular_state_set_service_state(NETCONFIG_CELLULAR_CONNECTING);
334
335                                 if (g_strcmp0(path, netconfig_get_default_profile()) != 0) {
336                                         g_free(property);
337                                         goto done;
338                                 }
339
340                                 netconfig_update_default_profile(NULL);
341                         }
342                 }
343                 g_free(property);
344         } else if (g_strcmp0(sigvalue, "Proxy") == 0) {
345                 if (netconfig_is_wifi_profile(path) != TRUE || g_strcmp0(path, netconfig_get_default_profile()) != 0)
346                         goto done;
347
348                 if (!g_variant_type_equal(variant, G_VARIANT_TYPE_ARRAY))
349                         goto done;
350
351                 g_variant_get(variant, "a{sv}", &iter);
352                 while (g_variant_iter_loop(iter, "{sv}", &property, &var)) {
353                         if (g_strcmp0(property, "Servers") == 0) {
354                                 GVariantIter *iter_sub = NULL;
355
356                                 g_variant_get(var, "as", &iter_sub);
357                                 g_variant_iter_loop(iter_sub, "s", &value);
358                                 g_variant_iter_free(iter_sub);
359
360                                 DBG("Proxy - [%s]", value);
361                                 vconf_set_str(VCONFKEY_NETWORK_PROXY, value);
362
363                                 g_free(property);
364                                 g_variant_unref(var);
365                                 break;
366                         } else if (g_strcmp0(property, "Method") == 0) {
367                                 value = g_variant_get_string(var, NULL);
368                                 DBG("Method - [%s]", value);
369
370                                 if (g_strcmp0(value, "direct") == 0)
371                                         vconf_set_str(VCONFKEY_NETWORK_PROXY, "");
372
373                                 g_free(property);
374                                 g_variant_unref(var);
375                                 break;
376                         }
377                 }
378
379                 g_variant_iter_free(iter);
380         } else if (g_strcmp0(sigvalue, "IPv4") == 0) {
381                 __netconfig_extract_ipv4_signal_data(variant, path);
382         } else if (g_strcmp0(sigvalue, "IPv6") == 0) {
383                 __netconfig_extract_ipv6_signal_data(variant, path);
384         } else if (g_strcmp0(sigvalue, "Error") == 0) {
385                 g_variant_get(variant, "s", &property);
386                 INFO("[%s] Property : %s", sigvalue, property);
387                 g_free(property);
388         }
389 done:
390         if (sigvalue)
391                 g_free(sigvalue);
392
393         if (variant)
394                 g_variant_unref(variant);
395
396         return;
397 }
398
399 static void _dbus_name_changed_cb(GDBusConnection *conn,
400                 const gchar *Name, const gchar *path, const gchar *interface,
401                 const gchar *sig, GVariant *param, gpointer user_data)
402 {
403         gchar *name = NULL;
404         gchar *old = NULL;
405         gchar *new = NULL;
406
407         if (param == NULL)
408                 return;
409
410         g_variant_get(param, "(sss)", &name, &old, &new);
411
412         if (g_strcmp0(name, CONNMAN_SERVICE) == 0 && *new == '\0') {
413                 DBG("ConnMan destroyed: name %s, old %s, new %s", name, old, new);
414
415                 connman_register_agent();
416         }
417         if (name)
418                 g_free(name);
419         if (old)
420                 g_free(old);
421         if (new)
422                 g_free(new);
423
424         return;
425 }
426
427 static void _services_changed_cb(GDBusConnection *conn, const gchar *name,
428                 const gchar *path, const gchar *interface, const gchar *sig,
429                 GVariant *param, gpointer user_data)
430 {
431         gchar *property, *value;
432         gchar *service_path;
433         GVariant *variant = NULL;
434         GVariantIter *added = NULL, *removed = NULL, *next = NULL;
435
436         if (path == NULL || param == NULL)
437                 return;
438
439         if (g_strcmp0(sig, CONNMAN_SIGNAL_SERVICES_CHANGED) != 0)
440                 return;
441
442         if (netconfig_get_default_profile() != NULL)
443                 return;
444
445         g_variant_get(param, "(a(oa{sv})ao)", &added, &removed);
446
447         while (g_variant_iter_loop(added, "(oa{sv})", &service_path, &next)) {
448                 gboolean is_wifi_prof, is_cell_prof, is_cell_internet_prof;
449                 is_wifi_prof = netconfig_is_wifi_profile(service_path);
450                 is_cell_prof = netconfig_is_cellular_profile(service_path);
451                 is_cell_internet_prof = netconfig_is_cellular_internet_profile(
452                                 service_path);
453                 if (service_path != NULL) {
454                         while (next && g_variant_iter_loop(next, "{sv}", &property,
455                                                 &variant)) {
456                                 if (g_strcmp0(property, "State") == 0) {
457                                         g_variant_get(variant, "s", &value);
458                                         DBG("Profile %s State %s", service_path,
459                                                         value);
460                                         if (g_strcmp0(value, "ready") != 0 &&
461                                                         g_strcmp0(value,
462                                                                 "online") != 0) {
463                                                 g_free(property);
464                                                 g_free(value);
465                                                 g_variant_unref(variant);
466                                                 break;
467                                         }
468
469                                         if (!is_cell_prof)
470                                                 netconfig_update_default_profile(
471                                                                 service_path);
472                                         else if (is_cell_internet_prof) {
473                                                 netconfig_update_default_profile(
474                                                                 service_path);
475                                         }
476                                         if (is_wifi_prof)
477                                                 wifi_state_set_service_state(
478                                                         NETCONFIG_WIFI_CONNECTED);
479                                         else if (is_cell_prof &&
480                                                         is_cell_internet_prof)
481                                                 cellular_state_set_service_state(
482                                                         NETCONFIG_CELLULAR_ONLINE);
483                                         g_free(property);
484                                         g_free(value);
485                                         g_variant_unref(variant);
486                                         break;
487                                 }
488                         }
489                 }
490         }
491
492         g_variant_iter_free(added);
493
494         if (next)
495                 g_variant_iter_free(next);
496
497         if (removed)
498                 g_variant_iter_free(removed);
499
500         return;
501 }
502
503 static void _supplicant_interface_removed(GDBusConnection *conn,
504                 const gchar *name, const gchar *path, const gchar *interface,
505                 const gchar *sig, GVariant *param, gpointer user_data)
506 {
507         DBG("Interface removed handling!");
508         if (netconfig_wifi_is_bssid_scan_started() == TRUE)
509                 netconfig_wifi_bssid_signal_scanaborted();
510
511         return;
512 }
513
514 static void _supplicant_properties_changed(GDBusConnection *conn,
515                 const gchar *name, const gchar *path, const gchar *interface,
516                 const gchar *sig, GVariant *param, gpointer user_data)
517 {
518         gchar *key;
519         GVariantIter *iter;
520         GVariant *variant;
521         gboolean scanning = FALSE;
522
523         if (param == NULL)
524                 return;
525
526         g_variant_get(param, "(a{sv})", &iter);
527         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
528                 if (g_strcmp0(key, "Scanning") == 0) {
529                         scanning = g_variant_get_boolean(variant);
530                         DBG("setting scanning %s", scanning ? "TRUE" : "FALSE");
531                         if (scanning == TRUE)
532                                 netconfig_wifi_set_scanning(TRUE);
533                         else
534                                 netconfig_wifi_set_scanning(FALSE);
535
536                         g_variant_unref(variant);
537                         g_free(key);
538                         break;
539                 }
540         }
541
542         g_variant_iter_free(iter);
543
544         return;
545 }
546
547 static void _supplicant_bss_added(GDBusConnection *conn,
548                 const gchar *name, const gchar *path, const gchar *interface,
549                 const gchar *sig, GVariant *param, gpointer user_data)
550 {
551         DBG("BSS added handling!");
552         wifi_state_set_bss_found(TRUE);
553
554         return;
555 }
556
557 static void _supplicant_scan_done(GDBusConnection *conn,
558                 const gchar *name, const gchar *path, const gchar *interface,
559                 const gchar *sig, GVariant *param, gpointer user_data)
560 {
561         DBG("Scan Done handling!");
562         netconfig_wifi_set_scanning(FALSE);
563
564         if (netconfig_wifi_is_bssid_scan_started() == TRUE) {
565                 netconfig_wifi_bssid_signal_scandone();
566                 if (wifi_state_get_technology_state() < NETCONFIG_WIFI_TECH_POWERED)
567                         return;
568         }
569
570         if (netconfig_wifi_get_bgscan_state() == TRUE) {
571                 if (wifi_state_get_technology_state() >=
572                                 NETCONFIG_WIFI_TECH_POWERED)
573                         netconfig_wifi_bgscan_start(FALSE);
574
575                 wifi_start_timer_network_notification();
576         }
577
578         return;
579 }
580
581 static void _supplicant_driver_hanged(GDBusConnection *conn,
582                 const gchar *name, const gchar *path, const gchar *interface,
583                 const gchar *sig, GVariant *param, gpointer user_data)
584 {
585         DBG("Driver Hanged handling!");
586         ERR("Critical. Wi-Fi firmware crashed");
587
588         wifi_power_recover_firmware();
589
590         return;
591 }
592
593 static void _supplicant_session_overlapped(GDBusConnection *conn,
594                 const gchar *name, const gchar *path, const gchar *interface,
595                 const gchar *sig, GVariant *param, gpointer user_data)
596 {
597         DBG("Driver session overlapped handling!");
598         ERR("WPS PBC SESSION OVERLAPPED");
599 #if defined TIZEN_WEARABLE
600         return;
601 #else
602         netconfig_send_message_to_net_popup("WPS Error",
603                                         "wps session overlapped", "popup", NULL);
604 #endif
605 }
606
607 static void _supplicant_tdls_connected(GDBusConnection *conn,
608                 const gchar *name, const gchar *path, const gchar *interface,
609                 const gchar *sig, GVariant *param, gpointer user_data)
610 {
611         DBG("Received TDLS Connected Signal");
612         netconfig_wifi_tdls_connected_event(param);
613
614         return;
615 }
616
617 static void _supplicant_tdls_disconnected(GDBusConnection *conn,
618                 const gchar *name, const gchar *path, const gchar *interface,
619                 const gchar *sig, GVariant *param, gpointer user_data)
620 {
621         DBG("Received TDLS Disconnected Signal");
622         netconfig_wifi_tdls_disconnected_event(param);
623
624         return;
625 }
626
627 static void _supplicant_tdls_peer_found(GDBusConnection *conn,
628                 const gchar *name, const gchar *path, const gchar *interface,
629                 const gchar *sig, GVariant *param, gpointer user_data)
630 {
631         DBG("Received TDLS Peer Found Signal");
632         netconfig_wifi_tdls_peer_found_event(param);
633         return;
634 }
635
636 static void _supplicant_wifi_wps_connected(GVariant *param)
637 {
638         gchar *key;
639         char ssid[32] = {0, };
640         gchar *name;
641         GVariantIter *iter;
642         GVariant *variant;
643         int config_error = 0;
644         int error_indication = 0;
645         gsize ssid_len = 0;
646
647         if (param == NULL) {
648                 ERR("Param is NULL");
649                 return;
650         }
651
652         g_variant_get(param, "(sa{sv})", &name, &iter);
653         INFO("wps Result: %s", name);
654         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
655                 INFO("wps Key is %s", key);
656                 if (g_strcmp0(key, "SSID") == 0) {
657                         const char *t_key = NULL;
658                         t_key = g_variant_get_fixed_array(variant, &ssid_len, sizeof(guchar));
659                         INFO("wps ssid_len is %d ", ssid_len);
660                         if (t_key == NULL) {
661                                 g_free(key);
662                                 g_variant_unref(variant);
663                                 ERR("WPS PBC Connection Failed");
664                                 goto error;
665                         }
666                         if (ssid_len > 0 && ssid_len <= 32) {
667                                 memcpy(ssid, t_key, ssid_len);
668                         } else {
669                                 memset(ssid, 0, sizeof(ssid));
670                                 ssid_len = 0;
671                         }
672                         INFO("WPS PBC Connection completed with AP %s", ssid);
673                         netconfig_wifi_notify_wps_completed(ssid, ssid_len);
674                 }
675         }
676
677         g_variant_iter_free(iter);
678         g_free(name);
679         return;
680
681 error:
682         g_variant_iter_free(iter);
683         g_free(name);
684         error_indication = WPS_EI_OPERATION_FAILED;
685         config_error = WPS_CFG_NO_ERROR;
686         ERR("Error Occured! Notifying Fail Event");
687         netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
688
689 }
690
691 static void _supplicant_wifi_wps_event(GVariant *param)
692 {
693         gchar *key;
694         gchar *name;
695         GVariantIter *iter;
696         GVariant *variant;
697         gint32 config_error = 0;
698         gint32 error_indication = 0;
699
700         if (param == NULL) {
701                 ERR("Param is NULL");
702                 return;
703         }
704
705         g_variant_get(param, "(sa{sv})", &name, &iter);
706         INFO("Event Result: %s", name);
707         if (g_strcmp0(name, "fail") == 0) {
708                 while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
709                         if (key == NULL)
710                                 goto error;
711                         INFO("Key is %s", key);
712                         if (g_strcmp0(key, "config_error") == 0) {
713                                 config_error = g_variant_get_int32(variant);
714                                 ERR("Config Error %d", config_error);
715                         } else if (g_strcmp0(key, "error_indication") == 0) {
716                                 error_indication = g_variant_get_int32(variant);
717                                 ERR("Error Indication %d", error_indication);
718                         }
719                 }
720                 netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
721         }
722
723         g_variant_iter_free(iter);
724         g_free(name);
725         return;
726
727 error:
728         g_variant_iter_free(iter);
729         g_free(name);
730         error_indication = WPS_EI_OPERATION_FAILED;
731         config_error = WPS_CFG_NO_ERROR;
732         ERR("Error Occured! Notifying Fail Event");
733         netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
734 }
735
736 static void _supplicant_wifi_wps_credentials(GVariant *param)
737 {
738         gchar *key;
739         char ssid[32];
740         char wps_key[100];
741         GVariantIter *iter;
742         GVariant *variant;
743         int config_error = 0;
744         int error_indication = 0;
745         gsize ssid_len = 0;
746
747         if (param == NULL) {
748                 ERR("Param is NULL");
749                 return;
750         }
751
752         g_variant_get(param, "(a{sv})", &iter);
753         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
754                 if (key == NULL)
755                         goto error;
756                 INFO("wps Key is %s", key);
757                 if (g_strcmp0(key, "Key") == 0) {
758                         gsize key_len = 0;
759                         const char *t_key = NULL;
760                         key_len = g_variant_get_size(variant);
761
762                         INFO("wps password len %d ", key_len);
763                         if (key_len > 0) {
764                                 t_key = g_variant_get_fixed_array(variant, &key_len, sizeof(guchar));
765                                 if (!t_key) {
766                                         g_free(key);
767                                         g_variant_unref(variant);
768                                         goto error;
769                                 }
770                                 strncpy(wps_key, t_key, key_len);
771                                 wps_key[key_len] = '\0';
772                                 INFO("WPS Key in process credentials %s", wps_key);
773                         } else
774                                 SLOGI("WPS AP Security ->Open");
775                 } else if (g_strcmp0(key, "SSID") == 0) {
776                         const char *t_key = NULL;
777                         t_key = g_variant_get_fixed_array(variant, &ssid_len, sizeof(guchar));
778                         INFO("wps ssid_len is %d ", ssid_len);
779                         if (!t_key) {
780                                 g_free(key);
781                                 g_variant_unref(variant);
782                                 goto error;
783                         }
784                         if (ssid_len > 0 && ssid_len <= 32) {
785                                 memcpy(ssid, t_key, ssid_len);
786                         } else {
787                                 memset(ssid, 0, sizeof(ssid));
788                                 ssid_len = 0;
789                         }
790                         INFO("SSID in process credentials %s", ssid);
791                 }
792         }
793
794         g_variant_iter_free(iter);
795
796 #if 0
797         /*
798          * Notify WPS Credentials only when requested through WPS PBC
799          * In case of WPS PIN connman will take care of notification
800          */
801         if (netconfig_get_wps_field() == TRUE)
802 #endif
803         netconfig_wifi_notify_wps_credentials(ssid, ssid_len, wps_key);
804         return;
805
806 error:
807         g_variant_iter_free(iter);
808         error_indication = WPS_EI_OPERATION_FAILED;
809         config_error = WPS_CFG_NO_ERROR;
810         ERR("Error Occured! Notifying Fail Event");
811         netconfig_wifi_notify_wps_fail_event(config_error, error_indication);
812 }
813
814 static void __netconfig_wps_signal_filter_handler(GDBusConnection *conn,
815                 const gchar *name, const gchar *path, const gchar *interface,
816                 const gchar *sig, GVariant *param, gpointer user_data)
817 {
818         if (g_strcmp0(sig, SIGNAL_WPS_CREDENTIALS) == 0) {
819                 INFO("Received wps CREDENTIALS Signal from Supplicant");
820                 _supplicant_wifi_wps_credentials(param);
821         } else if (g_strcmp0(sig, SIGNAL_WPS_EVENT) == 0) {
822                 INFO("Received wps EVENT Signal from Supplicant");
823                 _supplicant_wifi_wps_event(param);
824         } else if (g_strcmp0(sig, SIGNAL_WPS_CONNECTED) == 0) {
825                 INFO("Received WPSConnected Signal from Supplicant");
826                 _supplicant_wifi_wps_connected(param);
827         }
828
829         return;
830 }
831
832 static supplicant_signal_cb supplicant_cbs[SIG_MAX] = {
833                 _supplicant_interface_removed,
834                 _supplicant_properties_changed,
835                 _supplicant_bss_added,
836                 _supplicant_scan_done,
837                 _supplicant_driver_hanged,
838                 _supplicant_session_overlapped,
839                 _supplicant_tdls_connected,
840                 _supplicant_tdls_disconnected,
841                 _supplicant_tdls_peer_found
842 };
843
844 void register_gdbus_signal(void)
845 {
846         GDBusConnection *connection = NULL;
847         const char *interface = NULL;
848         SuppSigArrayIndex sig;
849         connection = netdbus_get_connection();
850
851         if (connection == NULL) {
852                 ERR("Failed to get GDbus Connection");
853                 return;
854         }
855
856         /* listening to messages from all objects as no path is specified */
857         /* see signals from the given interface */
858         conn_subscription_ids[0] = g_dbus_connection_signal_subscribe(
859                         connection,
860                         CONNMAN_SERVICE,
861                         CONNMAN_TECHNOLOGY_INTERFACE,
862                         NULL,
863                         NULL,
864                         NULL,
865                         G_DBUS_SIGNAL_FLAGS_NONE,
866                         _technology_signal_cb,
867                         NULL,
868                         NULL);
869
870         conn_subscription_ids[1] = g_dbus_connection_signal_subscribe(
871                         connection,
872                         CONNMAN_SERVICE,
873                         CONNMAN_SERVICE_INTERFACE,
874                         CONNMAN_SIGNAL_PROPERTY_CHANGED,
875                         NULL,
876                         NULL,
877                         G_DBUS_SIGNAL_FLAGS_NONE,
878                         _service_signal_cb,
879                         NULL,
880                         NULL);
881
882         conn_subscription_ids[2] = g_dbus_connection_signal_subscribe(
883                         connection,
884                         DBUS_SERVICE_DBUS,
885                         DBUS_INTERFACE_DBUS,
886                         CONNMAN_SIGNAL_NAME_CHANGED,
887                         NULL,
888                         CONNMAN_SERVICE,
889                         G_DBUS_SIGNAL_FLAGS_NONE,
890                         _dbus_name_changed_cb,
891                         NULL,
892                         NULL);
893
894         conn_subscription_ids[3] = g_dbus_connection_signal_subscribe(
895                         connection,
896                         CONNMAN_SERVICE,
897                         CONNMAN_MANAGER_INTERFACE,
898                         CONNMAN_SIGNAL_SERVICES_CHANGED,
899                         NULL,
900                         NULL,
901                         G_DBUS_SIGNAL_FLAGS_NONE,
902                         _services_changed_cb,
903                         NULL,
904                         NULL);
905
906         INFO("Successfully register connman DBus signal filters");
907
908         conn_subscription_ids[4] = g_dbus_connection_signal_subscribe(
909                         connection,
910                         SUPPLICANT_SERVICE,
911                         SUPPLICANT_INTERFACE ".Interface.WPS",
912                         NULL,
913                         NULL,
914                         NULL,
915                         G_DBUS_SIGNAL_FLAGS_NONE,
916                         __netconfig_wps_signal_filter_handler,
917                         NULL,
918                         NULL);
919
920         INFO("Successfully register Supplicant WPS DBus signal filters");
921
922         for (sig = SIG_INTERFACE_REMOVED; sig < SIG_MAX; sig++) {
923                 /*
924                  * For SIG_INTERFACE_REMOVED INTERFACE_ADDED
925                  */
926                 interface = (sig == SIG_INTERFACE_REMOVED) ?
927                                 SUPPLICANT_INTERFACE : SUPPLICANT_IFACE_INTERFACE;
928
929                 supp_subscription_ids[sig] = g_dbus_connection_signal_subscribe(
930                                 connection,
931                                 SUPPLICANT_SERVICE,
932                                 interface,
933                                 supplicant_signals[sig],
934                                 NULL,
935                                 NULL,
936                                 G_DBUS_SIGNAL_FLAGS_NONE,
937                                 supplicant_cbs[sig],
938                                 NULL,
939                                 NULL);
940         }
941
942         INFO("Successfully register Supplicant DBus signal filters");
943
944         /* In case ConnMan precedes this signal register,
945          * net-config should update the default connected profile.
946          */
947         netconfig_update_default();
948 }
949
950 void deregister_gdbus_signal(void)
951 {
952         GDBusConnection *connection = NULL;
953         int signal;
954         SuppSigArrayIndex sig;
955         connection = netdbus_get_connection();
956         if (!connection) {
957                 ERR("Already de-registered. Nothing to be done");
958                 return;
959         }
960
961         for (signal = 0; signal < TOTAL_CONN_SIGNALS; signal++) {
962                 if (conn_subscription_ids[signal]) {
963                         g_dbus_connection_signal_unsubscribe(connection,
964                                                 conn_subscription_ids[signal]);
965                 }
966         }
967
968         for (sig = SIG_INTERFACE_REMOVED; sig < SIG_MAX; sig++) {
969                 if (supp_subscription_ids[sig]) {
970                         g_dbus_connection_signal_unsubscribe(connection,
971                                                 supp_subscription_ids[sig]);
972                 }
973         }
974
975 }