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