Added handling of "AssocStatusCode" signal
[platform/upstream/connman.git] / gsupplicant / supplicant.c
1 /*
2  *
3  *  WPA supplicant library with GLib integration
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdint.h>
31 #include <syslog.h>
32 #include <ctype.h>
33 #include <stdbool.h>
34 #include <netinet/if_ether.h>
35 #include <netinet/in.h>
36
37 #include <glib.h>
38 #include <gdbus.h>
39
40 #include "dbus.h"
41 #include "gsupplicant.h"
42
43 #define IEEE80211_CAP_ESS       0x0001
44 #define IEEE80211_CAP_IBSS      0x0002
45 #define IEEE80211_CAP_PRIVACY   0x0010
46
47 #define BSS_UNKNOWN_STRENGTH    -90
48
49 static DBusConnection *connection;
50
51 static const GSupplicantCallbacks *callbacks_pointer;
52
53 static dbus_bool_t system_available = FALSE;
54 static dbus_bool_t system_ready = FALSE;
55
56 static dbus_int32_t debug_level;
57 static dbus_bool_t debug_timestamp = FALSE;
58 static dbus_bool_t debug_showkeys = FALSE;
59
60 static const char *debug_strings[] = {
61         "msgdump", "debug", "info", "warning", "error", NULL
62 };
63
64 static unsigned int eap_methods;
65
66 struct strvalmap {
67         const char *str;
68         unsigned int val;
69 };
70
71 static struct strvalmap eap_method_map[] = {
72         { "MD5",        G_SUPPLICANT_EAP_METHOD_MD5     },
73         { "TLS",        G_SUPPLICANT_EAP_METHOD_TLS     },
74         { "MSCHAPV2",   G_SUPPLICANT_EAP_METHOD_MSCHAPV2        },
75         { "PEAP",       G_SUPPLICANT_EAP_METHOD_PEAP    },
76         { "TTLS",       G_SUPPLICANT_EAP_METHOD_TTLS    },
77         { "GTC",        G_SUPPLICANT_EAP_METHOD_GTC     },
78         { "OTP",        G_SUPPLICANT_EAP_METHOD_OTP     },
79         { "LEAP",       G_SUPPLICANT_EAP_METHOD_LEAP    },
80         { "WSC",        G_SUPPLICANT_EAP_METHOD_WSC     },
81         { }
82 };
83
84 static struct strvalmap keymgmt_map[] = {
85         { "none",               G_SUPPLICANT_KEYMGMT_NONE               },
86         { "ieee8021x",          G_SUPPLICANT_KEYMGMT_IEEE8021X  },
87         { "wpa-none",           G_SUPPLICANT_KEYMGMT_WPA_NONE   },
88         { "wpa-psk",            G_SUPPLICANT_KEYMGMT_WPA_PSK    },
89         { "wpa-psk-sha256",     G_SUPPLICANT_KEYMGMT_WPA_PSK_256        },
90         { "wpa-ft-psk",         G_SUPPLICANT_KEYMGMT_WPA_FT_PSK },
91         { "wpa-ft-eap",         G_SUPPLICANT_KEYMGMT_WPA_FT_EAP },
92         { "wpa-eap",            G_SUPPLICANT_KEYMGMT_WPA_EAP    },
93         { "wpa-eap-sha256",     G_SUPPLICANT_KEYMGMT_WPA_EAP_256        },
94         { "wps",                G_SUPPLICANT_KEYMGMT_WPS                },
95         { }
96 };
97
98 static struct strvalmap authalg_capa_map[] = {
99         { "open",       G_SUPPLICANT_CAPABILITY_AUTHALG_OPEN    },
100         { "shared",     G_SUPPLICANT_CAPABILITY_AUTHALG_SHARED  },
101         { "leap",       G_SUPPLICANT_CAPABILITY_AUTHALG_LEAP    },
102         { }
103 };
104
105 static struct strvalmap proto_capa_map[] = {
106         { "wpa",        G_SUPPLICANT_CAPABILITY_PROTO_WPA               },
107         { "rsn",        G_SUPPLICANT_CAPABILITY_PROTO_RSN               },
108         { }
109 };
110
111 static struct strvalmap group_map[] = {
112         { "wep40",      G_SUPPLICANT_GROUP_WEP40        },
113         { "wep104",     G_SUPPLICANT_GROUP_WEP104       },
114         { "tkip",       G_SUPPLICANT_GROUP_TKIP },
115         { "ccmp",       G_SUPPLICANT_GROUP_CCMP },
116         { }
117 };
118
119 static struct strvalmap pairwise_map[] = {
120         { "none",       G_SUPPLICANT_PAIRWISE_NONE      },
121         { "tkip",       G_SUPPLICANT_PAIRWISE_TKIP      },
122         { "ccmp",       G_SUPPLICANT_PAIRWISE_CCMP      },
123         { }
124 };
125
126 static struct strvalmap scan_capa_map[] = {
127         { "active",     G_SUPPLICANT_CAPABILITY_SCAN_ACTIVE     },
128         { "passive",    G_SUPPLICANT_CAPABILITY_SCAN_PASSIVE    },
129         { "ssid",       G_SUPPLICANT_CAPABILITY_SCAN_SSID               },
130         { }
131 };
132
133 static struct strvalmap mode_capa_map[] = {
134         { "infrastructure",     G_SUPPLICANT_CAPABILITY_MODE_INFRA      },
135         { "ad-hoc",             G_SUPPLICANT_CAPABILITY_MODE_IBSS       },
136         { "ap",                 G_SUPPLICANT_CAPABILITY_MODE_AP         },
137         { "p2p",                G_SUPPLICANT_CAPABILITY_MODE_P2P        },
138         { }
139 };
140
141 static GHashTable *interface_table;
142 static GHashTable *bss_mapping;
143 static GHashTable *peer_mapping;
144 static GHashTable *group_mapping;
145 static GHashTable *pending_peer_connection;
146
147 struct _GSupplicantWpsCredentials {
148         unsigned char ssid[32];
149         unsigned int ssid_len;
150         char *key;
151 };
152
153 struct _GSupplicantInterface {
154         char *path;
155         char *network_path;
156         unsigned int keymgmt_capa;
157         unsigned int authalg_capa;
158         unsigned int proto_capa;
159         unsigned int group_capa;
160         unsigned int pairwise_capa;
161         unsigned int scan_capa;
162         unsigned int mode_capa;
163         unsigned int max_scan_ssids;
164         bool p2p_support;
165         bool p2p_finding;
166         dbus_bool_t ready;
167         GSupplicantState state;
168         dbus_bool_t scanning;
169         GSupplicantInterfaceCallback scan_callback;
170         void *scan_data;
171         int apscan;
172         char *ifname;
173         char *driver;
174         char *bridge;
175         struct _GSupplicantWpsCredentials wps_cred;
176         GSupplicantWpsState wps_state;
177         GHashTable *network_table;
178         GHashTable *peer_table;
179         GHashTable *group_table;
180         GHashTable *net_mapping;
181         GHashTable *bss_mapping;
182         void *data;
183         const char *pending_peer_path;
184 #if defined TIZEN_EXT
185         int disconnect_reason;
186 #endif
187 };
188
189 struct g_supplicant_bss {
190         GSupplicantInterface *interface;
191         char *path;
192         unsigned char bssid[6];
193         unsigned char ssid[32];
194         unsigned int ssid_len;
195         dbus_uint16_t frequency;
196         dbus_uint32_t maxrate;
197         dbus_int16_t signal;
198         GSupplicantMode mode;
199         GSupplicantSecurity security;
200         dbus_bool_t rsn_selected;
201         unsigned int wpa_keymgmt;
202         unsigned int wpa_pairwise;
203         unsigned int wpa_group;
204         unsigned int rsn_keymgmt;
205         unsigned int rsn_pairwise;
206         unsigned int rsn_group;
207         unsigned int keymgmt;
208         dbus_bool_t privacy;
209         dbus_bool_t psk;
210         dbus_bool_t ieee8021x;
211 #if defined TIZEN_EXT
212         dbus_bool_t ft_psk;
213         dbus_bool_t ft_ieee8021x;
214         char *wifi_vsie;
215         unsigned int wifi_vsie_len;
216 #endif
217         unsigned int wps_capabilities;
218 };
219
220 struct _GSupplicantNetwork {
221         GSupplicantInterface *interface;
222         char *path;
223         char *group;
224         char *name;
225         unsigned char ssid[32];
226         unsigned int ssid_len;
227         dbus_int16_t signal;
228         dbus_uint16_t frequency;
229         struct g_supplicant_bss *best_bss;
230         GSupplicantMode mode;
231         GSupplicantSecurity security;
232         dbus_bool_t wps;
233         unsigned int wps_capabilities;
234         GHashTable *bss_table;
235         GHashTable *config_table;
236 #if defined TIZEN_EXT
237         unsigned int isHS20AP;
238         char *eap;
239         char *identity;
240         char *phase2;
241         unsigned int keymgmt;
242         char *wifi_vsie;
243         unsigned int wifi_vsie_len;
244 #endif
245 };
246
247 struct _GSupplicantPeer {
248         GSupplicantInterface *interface;
249         char *path;
250         unsigned char device_address[ETH_ALEN];
251         unsigned char iface_address[ETH_ALEN];
252         char *name;
253         unsigned char *widi_ies;
254         int widi_ies_length;
255         char *identifier;
256         unsigned int wps_capabilities;
257         GSList *groups;
258         const GSupplicantInterface *current_group_iface;
259         bool connection_requested;
260 };
261
262 struct _GSupplicantGroup {
263         GSupplicantInterface *interface;
264         GSupplicantInterface *orig_interface;
265         char *path;
266         int role;
267         GSList *members;
268 };
269
270 static inline void debug(const char *format, ...)
271 {
272         char str[256];
273         va_list ap;
274
275         if (!callbacks_pointer->debug)
276                 return;
277
278         va_start(ap, format);
279
280         if (vsnprintf(str, sizeof(str), format, ap) > 0)
281                 callbacks_pointer->debug(str);
282
283         va_end(ap);
284 }
285
286 #define SUPPLICANT_DBG(fmt, arg...) \
287         debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg);
288
289 static GSupplicantMode string2mode(const char *mode)
290 {
291         if (!mode)
292                 return G_SUPPLICANT_MODE_UNKNOWN;
293
294         if (g_str_equal(mode, "infrastructure"))
295                 return G_SUPPLICANT_MODE_INFRA;
296         else if (g_str_equal(mode, "ad-hoc"))
297                 return G_SUPPLICANT_MODE_IBSS;
298
299         return G_SUPPLICANT_MODE_UNKNOWN;
300 }
301
302 static const char *mode2string(GSupplicantMode mode)
303 {
304         switch (mode) {
305         case G_SUPPLICANT_MODE_UNKNOWN:
306                 break;
307         case G_SUPPLICANT_MODE_INFRA:
308                 return "managed";
309         case G_SUPPLICANT_MODE_IBSS:
310                 return "adhoc";
311         case G_SUPPLICANT_MODE_MASTER:
312                 return "ap";
313         }
314
315         return NULL;
316 }
317
318 static const char *security2string(GSupplicantSecurity security)
319 {
320         switch (security) {
321         case G_SUPPLICANT_SECURITY_UNKNOWN:
322                 break;
323         case G_SUPPLICANT_SECURITY_NONE:
324                 return "none";
325         case G_SUPPLICANT_SECURITY_WEP:
326                 return "wep";
327         case G_SUPPLICANT_SECURITY_PSK:
328                 return "psk";
329         case G_SUPPLICANT_SECURITY_IEEE8021X:
330                 return "ieee8021x";
331 #if defined TIZEN_EXT
332         case G_SUPPLICANT_SECURITY_FT_PSK:
333                 return "ft_psk";
334         case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
335                 return "ft_ieee8021x";
336 #endif
337         }
338
339         return NULL;
340 }
341
342 static GSupplicantState string2state(const char *state)
343 {
344         if (!state)
345                 return G_SUPPLICANT_STATE_UNKNOWN;
346
347         if (g_str_equal(state, "unknown"))
348                 return G_SUPPLICANT_STATE_UNKNOWN;
349         else if (g_str_equal(state, "interface_disabled"))
350                 return G_SUPPLICANT_STATE_DISABLED;
351         else if (g_str_equal(state, "disconnected"))
352                 return G_SUPPLICANT_STATE_DISCONNECTED;
353         else if (g_str_equal(state, "inactive"))
354                 return G_SUPPLICANT_STATE_INACTIVE;
355         else if (g_str_equal(state, "scanning"))
356                 return G_SUPPLICANT_STATE_SCANNING;
357         else if (g_str_equal(state, "authenticating"))
358                 return G_SUPPLICANT_STATE_AUTHENTICATING;
359         else if (g_str_equal(state, "associating"))
360                 return G_SUPPLICANT_STATE_ASSOCIATING;
361         else if (g_str_equal(state, "associated"))
362                 return G_SUPPLICANT_STATE_ASSOCIATED;
363         else if (g_str_equal(state, "group_handshake"))
364                 return G_SUPPLICANT_STATE_GROUP_HANDSHAKE;
365         else if (g_str_equal(state, "4way_handshake"))
366                 return G_SUPPLICANT_STATE_4WAY_HANDSHAKE;
367         else if (g_str_equal(state, "completed"))
368                 return G_SUPPLICANT_STATE_COMPLETED;
369
370         return G_SUPPLICANT_STATE_UNKNOWN;
371 }
372
373 static void callback_system_ready(void)
374 {
375         if (system_ready)
376                 return;
377
378         system_ready = TRUE;
379
380         if (!callbacks_pointer)
381                 return;
382
383         if (!callbacks_pointer->system_ready)
384                 return;
385
386         callbacks_pointer->system_ready();
387 }
388
389 static void callback_system_killed(void)
390 {
391         system_ready = FALSE;
392
393         if (!callbacks_pointer)
394                 return;
395
396         if (!callbacks_pointer->system_killed)
397                 return;
398
399         callbacks_pointer->system_killed();
400 }
401
402 static void callback_interface_added(GSupplicantInterface *interface)
403 {
404         SUPPLICANT_DBG("");
405
406         if (!callbacks_pointer)
407                 return;
408
409         if (!callbacks_pointer->interface_added)
410                 return;
411
412         callbacks_pointer->interface_added(interface);
413 }
414
415 static void callback_interface_state(GSupplicantInterface *interface)
416 {
417         if (!callbacks_pointer)
418                 return;
419
420         if (!callbacks_pointer->interface_state)
421                 return;
422
423         callbacks_pointer->interface_state(interface);
424 }
425
426 static void callback_interface_removed(GSupplicantInterface *interface)
427 {
428         if (!callbacks_pointer)
429                 return;
430
431         if (!callbacks_pointer->interface_removed)
432                 return;
433
434         callbacks_pointer->interface_removed(interface);
435 }
436
437 #if !defined TIZEN_EXT
438 static void callback_p2p_support(GSupplicantInterface *interface)
439 {
440         SUPPLICANT_DBG("");
441
442         if (!interface->p2p_support)
443                 return;
444
445         if (callbacks_pointer && callbacks_pointer->p2p_support)
446                 callbacks_pointer->p2p_support(interface);
447 }
448 #endif
449
450 static void callback_scan_started(GSupplicantInterface *interface)
451 {
452         if (!callbacks_pointer)
453                 return;
454
455         if (!callbacks_pointer->scan_started)
456                 return;
457
458         callbacks_pointer->scan_started(interface);
459 }
460
461 static void callback_scan_finished(GSupplicantInterface *interface)
462 {
463         if (!callbacks_pointer)
464                 return;
465
466         if (!callbacks_pointer->scan_finished)
467                 return;
468
469         callbacks_pointer->scan_finished(interface);
470 }
471
472 static void callback_network_added(GSupplicantNetwork *network)
473 {
474         if (!callbacks_pointer)
475                 return;
476
477         if (!callbacks_pointer->network_added)
478                 return;
479
480         callbacks_pointer->network_added(network);
481 }
482
483 static void callback_network_removed(GSupplicantNetwork *network)
484 {
485         if (!callbacks_pointer)
486                 return;
487
488         if (!callbacks_pointer->network_removed)
489                 return;
490
491         callbacks_pointer->network_removed(network);
492 }
493
494 #if defined TIZEN_EXT
495 static void callback_network_merged(GSupplicantNetwork *network)
496 {
497         if (!callbacks_pointer)
498                 return;
499
500         if (!callbacks_pointer->network_merged)
501                 return;
502
503         callbacks_pointer->network_merged(network);
504 }
505 #endif
506
507 static void callback_network_changed(GSupplicantNetwork *network,
508                                         const char *property)
509 {
510         if (!callbacks_pointer)
511                 return;
512
513         if (!callbacks_pointer->network_changed)
514                 return;
515
516         callbacks_pointer->network_changed(network, property);
517 }
518
519 static void callback_peer_found(GSupplicantPeer *peer)
520 {
521         if (!callbacks_pointer)
522                 return;
523
524         if (!callbacks_pointer->peer_found)
525                 return;
526
527         callbacks_pointer->peer_found(peer);
528 }
529
530 static void callback_peer_lost(GSupplicantPeer *peer)
531 {
532         if (!callbacks_pointer)
533                 return;
534
535         if (!callbacks_pointer->peer_lost)
536                 return;
537
538         callbacks_pointer->peer_lost(peer);
539 }
540
541 static void callback_peer_changed(GSupplicantPeer *peer,
542                                                 GSupplicantPeerState state)
543 {
544         if (!callbacks_pointer)
545                 return;
546
547         if (!callbacks_pointer->peer_changed)
548                 return;
549
550         callbacks_pointer->peer_changed(peer, state);
551 }
552
553 static void callback_peer_request(GSupplicantPeer *peer)
554 {
555         if (!callbacks_pointer)
556                 return;
557
558         if (!callbacks_pointer->peer_request)
559                 return;
560
561         peer->connection_requested = true;
562
563         callbacks_pointer->peer_request(peer);
564 }
565
566 static void callback_disconnect_reason_code(GSupplicantInterface *interface,
567                                         int reason_code)
568 {
569         if (!callbacks_pointer)
570                 return;
571
572         if (!callbacks_pointer->disconnect_reasoncode)
573                 return;
574
575         if (reason_code != 0)
576                 callbacks_pointer->disconnect_reasoncode(interface,
577                                                         reason_code);
578 }
579
580 static void callback_assoc_status_code(GSupplicantInterface *interface,
581                                 int status_code)
582 {
583         if (!callbacks_pointer)
584                 return;
585
586         if (!callbacks_pointer->assoc_status_code)
587                 return;
588
589         callbacks_pointer->assoc_status_code(interface, status_code);
590
591 }
592
593 static void remove_group(gpointer data)
594 {
595         GSupplicantGroup *group = data;
596
597         if (group->members)
598                 g_slist_free_full(group->members, g_free);
599
600         g_free(group->path);
601         g_free(group);
602 }
603
604 static void remove_interface(gpointer data)
605 {
606         GSupplicantInterface *interface = data;
607
608         g_hash_table_destroy(interface->bss_mapping);
609         g_hash_table_destroy(interface->net_mapping);
610         g_hash_table_destroy(interface->network_table);
611         g_hash_table_destroy(interface->peer_table);
612         g_hash_table_destroy(interface->group_table);
613
614         if (interface->scan_callback) {
615                 SUPPLICANT_DBG("call interface %p callback %p scanning %d",
616                                 interface, interface->scan_callback,
617                                 interface->scanning);
618
619                 interface->scan_callback(-EIO, interface, interface->scan_data);
620                 interface->scan_callback = NULL;
621                 interface->scan_data = NULL;
622
623                 if (interface->scanning) {
624                         interface->scanning = FALSE;
625                         callback_scan_finished(interface);
626                 }
627         }
628
629         callback_interface_removed(interface);
630
631         g_free(interface->wps_cred.key);
632         g_free(interface->path);
633         g_free(interface->network_path);
634 #if defined TIZEN_EXT
635         interface->network_path = NULL;
636 #endif
637         g_free(interface->ifname);
638         g_free(interface->driver);
639         g_free(interface->bridge);
640         g_free(interface);
641 }
642
643 static void remove_network(gpointer data)
644 {
645         GSupplicantNetwork *network = data;
646
647         g_hash_table_destroy(network->bss_table);
648
649         callback_network_removed(network);
650
651         g_hash_table_destroy(network->config_table);
652
653         g_free(network->path);
654         g_free(network->group);
655         g_free(network->name);
656 #if defined TIZEN_EXT
657         g_free(network->eap);
658         g_free(network->identity);
659         g_free(network->phase2);
660 #endif
661 #if defined TIZEN_EXT
662         g_free(network->wifi_vsie);
663 #endif
664
665         g_free(network);
666 }
667
668 static void remove_bss(gpointer data)
669 {
670         struct g_supplicant_bss *bss = data;
671
672         g_free(bss->path);
673 #if defined TIZEN_EXT
674         g_free(bss->wifi_vsie);
675 #endif
676         g_free(bss);
677 }
678
679 static void remove_peer(gpointer data)
680 {
681         GSupplicantPeer *peer = data;
682
683         callback_peer_lost(peer);
684
685         if (peer->groups)
686                 g_slist_free_full(peer->groups, g_free);
687
688         if (peer_mapping)
689                 g_hash_table_remove(peer_mapping, peer->path);
690
691         if (pending_peer_connection)
692                 g_hash_table_remove(pending_peer_connection, peer->path);
693
694         g_free(peer->path);
695         g_free(peer->name);
696         g_free(peer->identifier);
697
698         g_free(peer);
699 }
700
701 static void debug_strvalmap(const char *label, struct strvalmap *map,
702                                                         unsigned int val)
703 {
704         int i;
705
706         for (i = 0; map[i].str; i++) {
707                 if (val & map[i].val)
708                         SUPPLICANT_DBG("%s: %s", label, map[i].str);
709         }
710 }
711
712 static void interface_capability_keymgmt(DBusMessageIter *iter, void *user_data)
713 {
714         GSupplicantInterface *interface = user_data;
715         const char *str = NULL;
716         int i;
717
718         dbus_message_iter_get_basic(iter, &str);
719         if (!str)
720                 return;
721
722         for (i = 0; keymgmt_map[i].str; i++)
723                 if (strcmp(str, keymgmt_map[i].str) == 0) {
724                         interface->keymgmt_capa |= keymgmt_map[i].val;
725                         break;
726                 }
727 }
728
729 static void interface_capability_authalg(DBusMessageIter *iter, void *user_data)
730 {
731         GSupplicantInterface *interface = user_data;
732         const char *str = NULL;
733         int i;
734
735         dbus_message_iter_get_basic(iter, &str);
736         if (!str)
737                 return;
738
739         for (i = 0; authalg_capa_map[i].str; i++)
740                 if (strcmp(str, authalg_capa_map[i].str) == 0) {
741                         interface->authalg_capa |= authalg_capa_map[i].val;
742                         break;
743                 }
744 }
745
746 static void interface_capability_proto(DBusMessageIter *iter, void *user_data)
747 {
748         GSupplicantInterface *interface = user_data;
749         const char *str = NULL;
750         int i;
751
752         dbus_message_iter_get_basic(iter, &str);
753         if (!str)
754                 return;
755
756         for (i = 0; proto_capa_map[i].str; i++)
757                 if (strcmp(str, proto_capa_map[i].str) == 0) {
758                         interface->proto_capa |= proto_capa_map[i].val;
759                         break;
760                 }
761 }
762
763 static void interface_capability_pairwise(DBusMessageIter *iter,
764                                                         void *user_data)
765 {
766         GSupplicantInterface *interface = user_data;
767         const char *str = NULL;
768         int i;
769
770         dbus_message_iter_get_basic(iter, &str);
771         if (!str)
772                 return;
773
774         for (i = 0; pairwise_map[i].str; i++)
775                 if (strcmp(str, pairwise_map[i].str) == 0) {
776                         interface->pairwise_capa |= pairwise_map[i].val;
777                         break;
778                 }
779 }
780
781 static void interface_capability_group(DBusMessageIter *iter, void *user_data)
782 {
783         GSupplicantInterface *interface = user_data;
784         const char *str = NULL;
785         int i;
786
787         dbus_message_iter_get_basic(iter, &str);
788         if (!str)
789                 return;
790
791         for (i = 0; group_map[i].str; i++)
792                 if (strcmp(str, group_map[i].str) == 0) {
793                         interface->group_capa |= group_map[i].val;
794                         break;
795                 }
796 }
797
798 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
799 {
800         GSupplicantInterface *interface = user_data;
801         const char *str = NULL;
802         int i;
803
804         dbus_message_iter_get_basic(iter, &str);
805         if (!str)
806                 return;
807
808         for (i = 0; scan_capa_map[i].str; i++)
809                 if (strcmp(str, scan_capa_map[i].str) == 0) {
810                         interface->scan_capa |= scan_capa_map[i].val;
811                         break;
812                 }
813 }
814
815 static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
816 {
817         GSupplicantInterface *interface = user_data;
818         const char *str = NULL;
819         int i;
820
821         dbus_message_iter_get_basic(iter, &str);
822         if (!str)
823                 return;
824
825         for (i = 0; mode_capa_map[i].str; i++)
826                 if (strcmp(str, mode_capa_map[i].str) == 0) {
827                         interface->mode_capa |= mode_capa_map[i].val;
828                         break;
829                 }
830 }
831
832 static void interface_capability(const char *key, DBusMessageIter *iter,
833                                                         void *user_data)
834 {
835         GSupplicantInterface *interface = user_data;
836
837         if (!key)
838                 return;
839
840         if (g_strcmp0(key, "KeyMgmt") == 0)
841                 supplicant_dbus_array_foreach(iter,
842                                 interface_capability_keymgmt, interface);
843         else if (g_strcmp0(key, "AuthAlg") == 0)
844                 supplicant_dbus_array_foreach(iter,
845                                 interface_capability_authalg, interface);
846         else if (g_strcmp0(key, "Protocol") == 0)
847                 supplicant_dbus_array_foreach(iter,
848                                 interface_capability_proto, interface);
849         else if (g_strcmp0(key, "Pairwise") == 0)
850                 supplicant_dbus_array_foreach(iter,
851                                 interface_capability_pairwise, interface);
852         else if (g_strcmp0(key, "Group") == 0)
853                 supplicant_dbus_array_foreach(iter,
854                                 interface_capability_group, interface);
855         else if (g_strcmp0(key, "Scan") == 0)
856                 supplicant_dbus_array_foreach(iter,
857                                 interface_capability_scan, interface);
858         else if (g_strcmp0(key, "Modes") == 0)
859                 supplicant_dbus_array_foreach(iter,
860                                 interface_capability_mode, interface);
861         else if (g_strcmp0(key, "MaxScanSSID") == 0) {
862                 dbus_int32_t max_scan_ssid;
863
864                 dbus_message_iter_get_basic(iter, &max_scan_ssid);
865                 if (max_scan_ssid < 2)
866                         max_scan_ssid = 0;
867                 interface->max_scan_ssids = max_scan_ssid;
868
869         } else
870                 SUPPLICANT_DBG("key %s type %c",
871                                 key, dbus_message_iter_get_arg_type(iter));
872 }
873
874 static void set_apscan(DBusMessageIter *iter, void *user_data)
875 {
876         unsigned int ap_scan = *(unsigned int *)user_data;
877
878         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ap_scan);
879 }
880
881 int g_supplicant_interface_set_apscan(GSupplicantInterface *interface,
882                                                         unsigned int ap_scan)
883 {
884         return supplicant_dbus_property_set(interface->path,
885                         SUPPLICANT_INTERFACE ".Interface",
886                                 "ApScan", DBUS_TYPE_UINT32_AS_STRING,
887                                         set_apscan, NULL, &ap_scan, NULL);
888 }
889
890 void g_supplicant_interface_set_data(GSupplicantInterface *interface,
891                                                                 void *data)
892 {
893         if (!interface)
894                 return;
895
896         interface->data = data;
897
898         if (!data)
899                 interface->scan_callback = NULL;
900 }
901
902 void *g_supplicant_interface_get_data(GSupplicantInterface *interface)
903 {
904         if (!interface)
905                 return NULL;
906
907         return interface->data;
908 }
909
910 const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
911 {
912         if (!interface)
913                 return NULL;
914
915         return interface->ifname;
916 }
917
918 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
919 {
920         if (!interface)
921                 return NULL;
922
923         return interface->driver;
924 }
925
926 GSupplicantState g_supplicant_interface_get_state(
927                                         GSupplicantInterface *interface)
928 {
929         if (!interface)
930                 return G_SUPPLICANT_STATE_UNKNOWN;
931
932         return interface->state;
933 }
934
935 const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface)
936 {
937         if (!interface)
938                 return NULL;
939
940         return (const char *)interface->wps_cred.key;
941 }
942
943 const void *g_supplicant_interface_get_wps_ssid(GSupplicantInterface *interface,
944                                                         unsigned int *ssid_len)
945 {
946         if (!ssid_len)
947                 return NULL;
948
949         if (!interface || interface->wps_cred.ssid_len == 0) {
950                 *ssid_len = 0;
951                 return NULL;
952         }
953
954         *ssid_len = interface->wps_cred.ssid_len;
955         return interface->wps_cred.ssid;
956 }
957
958 GSupplicantWpsState g_supplicant_interface_get_wps_state(
959                                         GSupplicantInterface *interface)
960 {
961         if (!interface)
962                 return G_SUPPLICANT_WPS_STATE_UNKNOWN;
963
964         return interface->wps_state;
965 }
966
967 unsigned int g_supplicant_interface_get_mode(GSupplicantInterface *interface)
968 {
969         if (!interface)
970                 return 0;
971
972         return interface->mode_capa;
973 }
974
975 unsigned int g_supplicant_interface_get_max_scan_ssids(
976                                 GSupplicantInterface *interface)
977 {
978         if (!interface)
979                 return 0;
980
981         if (interface->max_scan_ssids == 0)
982                 return WPAS_MAX_SCAN_SSIDS;
983
984         return interface->max_scan_ssids;
985 }
986
987 static void set_network_enabled(DBusMessageIter *iter, void *user_data)
988 {
989         dbus_bool_t enable = *(dbus_bool_t *)user_data;
990
991         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &enable);
992 }
993
994 int g_supplicant_interface_enable_selected_network(GSupplicantInterface *interface,
995                                                         dbus_bool_t enable)
996 {
997         if (!interface)
998                 return -1;
999
1000         if (!interface->network_path)
1001                 return -1;
1002
1003         SUPPLICANT_DBG(" ");
1004         return supplicant_dbus_property_set(interface->network_path,
1005                                 SUPPLICANT_INTERFACE ".Network",
1006                                 "Enabled", DBUS_TYPE_BOOLEAN_AS_STRING,
1007                                 set_network_enabled, NULL, &enable, NULL);
1008 }
1009
1010 dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
1011 {
1012         if (!interface)
1013                 return FALSE;
1014
1015         return interface->ready;
1016 }
1017
1018 GSupplicantInterface *g_supplicant_network_get_interface(
1019                                         GSupplicantNetwork *network)
1020 {
1021         if (!network)
1022                 return NULL;
1023
1024         return network->interface;
1025 }
1026
1027 const char *g_supplicant_network_get_name(GSupplicantNetwork *network)
1028 {
1029         if (!network || !network->name)
1030                 return "";
1031
1032         return network->name;
1033 }
1034
1035 const char *g_supplicant_network_get_identifier(GSupplicantNetwork *network)
1036 {
1037         if (!network || !network->group)
1038                 return "";
1039
1040         return network->group;
1041 }
1042
1043 const char *g_supplicant_network_get_path(GSupplicantNetwork *network)
1044 {
1045         if (!network || !network->path)
1046                 return NULL;
1047
1048         return network->path;
1049 }
1050
1051 const char *g_supplicant_network_get_mode(GSupplicantNetwork *network)
1052 {
1053         if (!network)
1054                 return G_SUPPLICANT_MODE_UNKNOWN;
1055
1056         return mode2string(network->mode);
1057 }
1058
1059 const char *g_supplicant_network_get_security(GSupplicantNetwork *network)
1060 {
1061         if (!network)
1062                 return G_SUPPLICANT_SECURITY_UNKNOWN;
1063
1064         return security2string(network->security);
1065 }
1066
1067 const void *g_supplicant_network_get_ssid(GSupplicantNetwork *network,
1068                                                 unsigned int *ssid_len)
1069 {
1070         if (!network) {
1071                 *ssid_len = 0;
1072                 return NULL;
1073         }
1074
1075         *ssid_len = network->ssid_len;
1076         return network->ssid;
1077 }
1078
1079 dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network)
1080 {
1081         if (!network)
1082                 return 0;
1083
1084         return network->signal;
1085 }
1086
1087 dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network)
1088 {
1089         if (!network)
1090                 return 0;
1091
1092         return network->frequency;
1093 }
1094
1095 dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
1096 {
1097         if (!network)
1098                 return FALSE;
1099
1100         return network->wps;
1101 }
1102
1103 dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
1104 {
1105         if (!network)
1106                 return FALSE;
1107
1108         if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
1109                 return TRUE;
1110
1111         return FALSE;
1112 }
1113
1114 dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
1115 {
1116         if (!network)
1117                 return FALSE;
1118
1119         if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1120                 return TRUE;
1121
1122         return FALSE;
1123 }
1124
1125 dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
1126 {
1127         if (!network)
1128                 return FALSE;
1129
1130         if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
1131                 return TRUE;
1132
1133         return FALSE;
1134 }
1135
1136 GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
1137 {
1138         if (!peer)
1139                 return NULL;
1140
1141         return peer->interface;
1142 }
1143
1144 const char *g_supplicant_peer_get_path(GSupplicantPeer *peer)
1145 {
1146         if (!peer)
1147                 return NULL;
1148
1149         return peer->path;
1150 }
1151
1152 const char *g_supplicant_peer_get_identifier(GSupplicantPeer *peer)
1153 {
1154         if (!peer)
1155                 return NULL;
1156
1157         return peer->identifier;
1158 }
1159
1160 const void *g_supplicant_peer_get_device_address(GSupplicantPeer *peer)
1161 {
1162         if (!peer)
1163                 return NULL;
1164
1165         return peer->device_address;
1166 }
1167
1168 const void *g_supplicant_peer_get_iface_address(GSupplicantPeer *peer)
1169 {
1170         if (!peer)
1171                 return NULL;
1172
1173         return peer->iface_address;
1174 }
1175
1176 const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
1177 {
1178         if (!peer)
1179                 return NULL;
1180
1181         return peer->name;
1182 }
1183
1184 #if defined TIZEN_EXT
1185 unsigned int g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
1186 {
1187         if (!network)
1188                 return 0;
1189
1190         return network->isHS20AP;
1191 }
1192
1193 const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
1194 {
1195         if (!network || !network->eap)
1196                 return NULL;
1197
1198         return network->eap;
1199 }
1200
1201 const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
1202 {
1203         if (!network || !network->identity)
1204                 return NULL;
1205
1206         return network->identity;
1207 }
1208
1209 const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
1210 {
1211         if (!network || !network->phase2)
1212                 return NULL;
1213
1214         return network->phase2;
1215 }
1216
1217 unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
1218 {
1219         if (network == NULL)
1220                 return 0;
1221
1222         return network->keymgmt;
1223 }
1224 #endif
1225
1226 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
1227                                                                 int *length)
1228 {
1229         if (!peer || !length)
1230                 return NULL;
1231
1232         *length = peer->widi_ies_length;
1233         return peer->widi_ies;
1234 }
1235
1236 bool g_supplicant_peer_is_wps_pbc(GSupplicantPeer *peer)
1237 {
1238         if (!peer)
1239                 return false;
1240
1241         if (peer->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1242                 return true;
1243
1244         return false;
1245 }
1246
1247 bool g_supplicant_peer_is_wps_pin(GSupplicantPeer *peer)
1248 {
1249         if (!peer)
1250                 return false;
1251
1252         if (peer->wps_capabilities & G_SUPPLICANT_WPS_PIN)
1253                 return true;
1254
1255         return false;
1256 }
1257
1258 bool g_supplicant_peer_is_in_a_group(GSupplicantPeer *peer)
1259 {
1260         if (!peer || !peer->groups)
1261                 return false;
1262
1263         return true;
1264 }
1265
1266 GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *peer)
1267 {
1268         if (!peer)
1269                 return NULL;
1270
1271         return (GSupplicantInterface *) peer->current_group_iface;
1272 }
1273
1274 bool g_supplicant_peer_is_client(GSupplicantPeer *peer)
1275 {
1276         GSupplicantGroup *group;
1277         GSList *list;
1278
1279         if (!peer)
1280                 return false;
1281
1282         for (list = peer->groups; list; list = list->next) {
1283                 const char *path = list->data;
1284
1285                 group = g_hash_table_lookup(group_mapping, path);
1286                 if (!group)
1287                         continue;
1288
1289                 if (group->role != G_SUPPLICANT_GROUP_ROLE_CLIENT ||
1290                                 group->orig_interface != peer->interface)
1291                         continue;
1292
1293                 if (group->interface == peer->current_group_iface)
1294                         return true;
1295         }
1296
1297         return false;
1298 }
1299
1300 bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
1301 {
1302         if (!peer)
1303                 return false;
1304
1305         return peer->connection_requested;
1306 }
1307
1308 #if defined TIZEN_EXT
1309 /*
1310  * Description: Network client requires additional wifi specific info
1311  */
1312 const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
1313 {
1314         if (network == NULL || network->best_bss == NULL)
1315                 return NULL;
1316
1317         return (const unsigned char *)network->best_bss->bssid;
1318 }
1319
1320 unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
1321 {
1322         if (network == NULL || network->best_bss == NULL)
1323                 return 0;
1324
1325         return network->best_bss->maxrate;
1326 }
1327
1328 const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
1329 {
1330         if (network == NULL || network->best_bss == NULL)
1331                 return NULL;
1332
1333         if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
1334             network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
1335                 unsigned int pairwise;
1336
1337                 pairwise = network->best_bss->rsn_pairwise |
1338                                 network->best_bss->wpa_pairwise;
1339
1340                 if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
1341                     (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
1342                         return "mixed";
1343                 else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
1344                         return "aes";
1345                 else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
1346                         return "tkip";
1347
1348         } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
1349                 return "wep";
1350         else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
1351                 return "none";
1352
1353         return NULL;
1354 }
1355
1356 bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
1357 {
1358         if (network == NULL || network->best_bss == NULL)
1359                 return 0;
1360
1361         if (network->best_bss->rsn_selected) {
1362                 const char *mode = g_supplicant_network_get_enc_mode(network);
1363                 if (g_strcmp0(mode, "aes") == 0 ||
1364                                 g_strcmp0(mode, "mixed") == 0)
1365                         return true;
1366                 else
1367                         return false;
1368         } else
1369                 return false;
1370 }
1371
1372 const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network,
1373                                                 unsigned int *wifi_vsie_len)
1374 {
1375         if (!network) {
1376                 *wifi_vsie_len = 0;
1377                 return NULL;
1378         }
1379
1380         *wifi_vsie_len = network->wifi_vsie_len;
1381         return network->wifi_vsie;
1382 }
1383 #endif
1384
1385 static void merge_network(GSupplicantNetwork *network)
1386 {
1387         GString *str;
1388         const char *ssid, *mode, *key_mgmt;
1389 #if defined TIZEN_EXT
1390         GSupplicantInterface *interface;
1391         const char *isHS20AP;
1392         const char *eap, *identity, *phase2;
1393 #endif
1394         unsigned int i, ssid_len;
1395         char *group;
1396
1397         ssid = g_hash_table_lookup(network->config_table, "ssid");
1398         mode = g_hash_table_lookup(network->config_table, "mode");
1399         key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
1400 #if defined TIZEN_EXT
1401         isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
1402         eap = g_hash_table_lookup(network->config_table, "eap");
1403         identity = g_hash_table_lookup(network->config_table, "identity");
1404         phase2 = g_hash_table_lookup(network->config_table, "phase2");
1405         interface = network->interface;
1406 #endif
1407
1408         SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
1409
1410         if (ssid)
1411                 ssid_len = strlen(ssid);
1412         else
1413                 ssid_len = 0;
1414
1415         str = g_string_sized_new((ssid_len * 2) + 24);
1416         if (!str)
1417                 return;
1418
1419         for (i = 0; i < ssid_len; i++)
1420 #if defined TIZEN_EXT
1421         {
1422                 if (ssid[i] != '"')
1423 #endif
1424                 g_string_append_printf(str, "%02x", ssid[i]);
1425 #if defined TIZEN_EXT
1426         }
1427 #endif
1428
1429         if (g_strcmp0(mode, "0") == 0)
1430                 g_string_append_printf(str, "_managed");
1431         else if (g_strcmp0(mode, "1") == 0)
1432                 g_string_append_printf(str, "_adhoc");
1433
1434         if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
1435                 g_string_append_printf(str, "_psk");
1436 #if defined TIZEN_EXT
1437         else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
1438                 g_string_append_printf(str, "_ieee8021x");
1439         else
1440                 g_string_append_printf(str, "_none");
1441 #endif
1442
1443         group = g_string_free(str, FALSE);
1444
1445         SUPPLICANT_DBG("%s", group);
1446
1447 #if defined TIZEN_EXT
1448         if (g_strcmp0(isHS20AP, "1") == 0) {
1449                 network->isHS20AP = 1;
1450                 if (network->eap)
1451                         g_free(network->eap);
1452                 network->eap = g_strdup(eap);
1453
1454                 if (network->identity)
1455                         g_free(network->identity);
1456                 network->identity = g_strdup(identity);
1457
1458                 if (network->phase2)
1459                         g_free(network->phase2);
1460                 network->phase2 = g_strdup(phase2);
1461         } else
1462                 network->isHS20AP = 0;
1463
1464         if (interface)
1465                 interface->network_path = g_strdup(network->path);
1466
1467         network->group = g_strdup(group);
1468         callback_network_merged(network);
1469 #endif
1470
1471         g_free(group);
1472
1473         g_hash_table_destroy(network->config_table);
1474
1475         g_free(network->path);
1476         g_free(network);
1477 }
1478
1479 static void network_property(const char *key, DBusMessageIter *iter,
1480                                                         void *user_data)
1481 {
1482         GSupplicantNetwork *network = user_data;
1483
1484         if (!network->interface)
1485                 return;
1486
1487         if (!key) {
1488                 merge_network(network);
1489                 return;
1490         }
1491
1492         if (g_strcmp0(key, "Enabled") == 0) {
1493                 dbus_bool_t enabled = FALSE;
1494
1495                 dbus_message_iter_get_basic(iter, &enabled);
1496         } else if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
1497                 const char *str = NULL;
1498
1499                 dbus_message_iter_get_basic(iter, &str);
1500                 if (str) {
1501                         g_hash_table_replace(network->config_table,
1502                                                 g_strdup(key), g_strdup(str));
1503                 }
1504         } else
1505                 SUPPLICANT_DBG("key %s type %c",
1506                                 key, dbus_message_iter_get_arg_type(iter));
1507 }
1508
1509 static void interface_network_added(DBusMessageIter *iter, void *user_data)
1510 {
1511         GSupplicantInterface *interface = user_data;
1512         GSupplicantNetwork *network;
1513         const char *path = NULL;
1514
1515         SUPPLICANT_DBG("");
1516
1517         dbus_message_iter_get_basic(iter, &path);
1518         if (!path)
1519                 return;
1520
1521         if (g_strcmp0(path, "/") == 0)
1522                 return;
1523
1524         network = g_hash_table_lookup(interface->net_mapping, path);
1525         if (network)
1526                 return;
1527
1528         network = g_try_new0(GSupplicantNetwork, 1);
1529         if (!network)
1530                 return;
1531
1532         network->interface = interface;
1533         network->path = g_strdup(path);
1534
1535         network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1536                                                         g_free, g_free);
1537
1538         dbus_message_iter_next(iter);
1539         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
1540                 supplicant_dbus_property_foreach(iter, network_property,
1541                                                                 network);
1542                 network_property(NULL, NULL, network);
1543                 return;
1544         }
1545
1546         supplicant_dbus_property_get_all(path,
1547                                 SUPPLICANT_INTERFACE ".Network",
1548                                         network_property, network, NULL);
1549 }
1550
1551 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
1552 {
1553         GSupplicantInterface *interface = user_data;
1554         GSupplicantNetwork *network;
1555         const char *path = NULL;
1556
1557         dbus_message_iter_get_basic(iter, &path);
1558         if (!path)
1559                 return;
1560
1561         network = g_hash_table_lookup(interface->net_mapping, path);
1562         if (!network)
1563                 return;
1564
1565         g_hash_table_remove(interface->net_mapping, path);
1566 }
1567
1568 static char *create_name(unsigned char *ssid, int ssid_len)
1569 {
1570         GString *string;
1571         const gchar *remainder, *invalid;
1572         int valid_bytes, remaining_bytes;
1573
1574         if (ssid_len < 1 || ssid[0] == '\0')
1575                 return g_strdup("");
1576
1577         string = NULL;
1578         remainder = (const gchar *)ssid;
1579         remaining_bytes = ssid_len;
1580
1581         while (remaining_bytes != 0) {
1582                 if (g_utf8_validate(remainder, remaining_bytes,
1583                                         &invalid)) {
1584                         break;
1585                 }
1586
1587                 valid_bytes = invalid - remainder;
1588
1589                 if (!string)
1590                         string = g_string_sized_new(remaining_bytes);
1591
1592                 g_string_append_len(string, remainder, valid_bytes);
1593
1594                 /* append U+FFFD REPLACEMENT CHARACTER */
1595                 g_string_append(string, "\357\277\275");
1596
1597                 remaining_bytes -= valid_bytes + 1;
1598                 remainder = invalid + 1;
1599         }
1600
1601         if (!string)
1602                 return g_strndup((const gchar *)ssid, ssid_len + 1);
1603
1604         g_string_append(string, remainder);
1605
1606         return g_string_free(string, FALSE);
1607 }
1608
1609 static char *create_group(struct g_supplicant_bss *bss)
1610 {
1611         GString *str;
1612         unsigned int i;
1613         const char *mode, *security;
1614
1615         str = g_string_sized_new((bss->ssid_len * 2) + 24);
1616         if (!str)
1617                 return NULL;
1618
1619         if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
1620                 for (i = 0; i < bss->ssid_len; i++)
1621                         g_string_append_printf(str, "%02x", bss->ssid[i]);
1622         } else
1623                 g_string_append_printf(str, "hidden");
1624
1625         mode = mode2string(bss->mode);
1626         if (mode)
1627                 g_string_append_printf(str, "_%s", mode);
1628
1629         security = security2string(bss->security);
1630         if (security)
1631                 g_string_append_printf(str, "_%s", security);
1632
1633         return g_string_free(str, FALSE);
1634 }
1635
1636 static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
1637 {
1638         GSupplicantInterface *interface = bss->interface;
1639         GSupplicantNetwork *network;
1640         char *group;
1641
1642         group = create_group(bss);
1643         SUPPLICANT_DBG("New group created: %s", group);
1644
1645         if (!group)
1646                 return;
1647
1648         network = g_hash_table_lookup(interface->network_table, group);
1649         if (network) {
1650                 g_free(group);
1651                 SUPPLICANT_DBG("Network %s already exist", network->name);
1652
1653                 goto done;
1654         }
1655
1656         network = g_try_new0(GSupplicantNetwork, 1);
1657         if (!network) {
1658                 g_free(group);
1659                 return;
1660         }
1661
1662         network->interface = interface;
1663         if (!network->path)
1664                 network->path = g_strdup(bss->path);
1665         network->group = group;
1666         network->name = create_name(bss->ssid, bss->ssid_len);
1667         network->mode = bss->mode;
1668         network->security = bss->security;
1669         network->ssid_len = bss->ssid_len;
1670         memcpy(network->ssid, bss->ssid, bss->ssid_len);
1671         network->signal = bss->signal;
1672         network->frequency = bss->frequency;
1673         network->best_bss = bss;
1674
1675 #if defined TIZEN_EXT
1676         network->keymgmt = bss->keymgmt;
1677
1678         if (bss->wifi_vsie_len > 0) {
1679                 SUPPLICANT_DBG("vsie len: %d", bss->wifi_vsie_len);
1680                 network->wifi_vsie = (char *)g_try_malloc0(bss->wifi_vsie_len);
1681                 if(network->wifi_vsie) {
1682                         network->wifi_vsie_len = bss->wifi_vsie_len;
1683                         memcpy(network->wifi_vsie, bss->wifi_vsie, network->wifi_vsie_len);
1684                 } else {
1685                         SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
1686                 }
1687         }
1688 #endif
1689
1690         SUPPLICANT_DBG("New network %s created", network->name);
1691
1692         network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1693                                                         NULL, remove_bss);
1694
1695         network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1696                                                         g_free, g_free);
1697
1698         g_hash_table_replace(interface->network_table,
1699                                                 network->group, network);
1700
1701         callback_network_added(network);
1702
1703 done:
1704         /* We update network's WPS properties if only bss provides WPS. */
1705         if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
1706                 network->wps = TRUE;
1707                 network->wps_capabilities |= bss->wps_capabilities;
1708         }
1709
1710         if (bss->signal > network->signal) {
1711                 network->signal = bss->signal;
1712                 network->best_bss = bss;
1713                 callback_network_changed(network, "Signal");
1714         }
1715
1716         g_hash_table_replace(interface->bss_mapping, bss->path, network);
1717         g_hash_table_replace(network->bss_table, bss->path, bss);
1718
1719         g_hash_table_replace(bss_mapping, bss->path, interface);
1720 }
1721
1722 static void bss_rates(DBusMessageIter *iter, void *user_data)
1723 {
1724         struct g_supplicant_bss *bss = user_data;
1725         dbus_uint32_t rate = 0;
1726
1727         dbus_message_iter_get_basic(iter, &rate);
1728         if (rate == 0)
1729                 return;
1730
1731         if (rate > bss->maxrate)
1732                 bss->maxrate = rate;
1733 }
1734
1735 static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
1736 {
1737         unsigned int *keymgmt = user_data;
1738         const char *str = NULL;
1739         int i;
1740
1741         dbus_message_iter_get_basic(iter, &str);
1742         if (!str)
1743                 return;
1744
1745         for (i = 0; keymgmt_map[i].str; i++)
1746                 if (strcmp(str, keymgmt_map[i].str) == 0) {
1747                         SUPPLICANT_DBG("Keymgmt: %s", str);
1748                         *keymgmt |= keymgmt_map[i].val;
1749                         break;
1750                 }
1751 }
1752
1753 static void bss_group(DBusMessageIter *iter, void *user_data)
1754 {
1755         unsigned int *group = user_data;
1756         const char *str = NULL;
1757         int i;
1758
1759         dbus_message_iter_get_basic(iter, &str);
1760         if (!str)
1761                 return;
1762
1763         for (i = 0; group_map[i].str; i++)
1764                 if (strcmp(str, group_map[i].str) == 0) {
1765                         SUPPLICANT_DBG("Group: %s", str);
1766                         *group |= group_map[i].val;
1767                         break;
1768                 }
1769 }
1770
1771 static void bss_pairwise(DBusMessageIter *iter, void *user_data)
1772 {
1773         unsigned int *pairwise = user_data;
1774         const char *str = NULL;
1775         int i;
1776
1777         dbus_message_iter_get_basic(iter, &str);
1778         if (!str)
1779                 return;
1780
1781         for (i = 0; pairwise_map[i].str; i++)
1782                 if (strcmp(str, pairwise_map[i].str) == 0) {
1783                         SUPPLICANT_DBG("Pairwise: %s", str);
1784                         *pairwise |= pairwise_map[i].val;
1785                         break;
1786                 }
1787 }
1788
1789 static void bss_wpa(const char *key, DBusMessageIter *iter,
1790                         void *user_data)
1791 {
1792         struct g_supplicant_bss *bss = user_data;
1793         unsigned int value = 0;
1794
1795         SUPPLICANT_DBG("Key: %s", key);
1796
1797         if (g_strcmp0(key, "KeyMgmt") == 0) {
1798                 supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
1799
1800                 if (bss->rsn_selected)
1801                         bss->rsn_keymgmt = value;
1802                 else
1803                         bss->wpa_keymgmt = value;
1804         } else if (g_strcmp0(key, "Group") == 0) {
1805                 supplicant_dbus_array_foreach(iter, bss_group, &value);
1806
1807                 if (bss->rsn_selected)
1808                         bss->rsn_group = value;
1809                 else
1810                         bss->wpa_group = value;
1811         } else if (g_strcmp0(key, "Pairwise") == 0) {
1812                 supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
1813
1814                 if (bss->rsn_selected)
1815                         bss->rsn_pairwise = value;
1816                 else
1817                         bss->wpa_pairwise = value;
1818         }
1819 }
1820
1821 static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
1822                                                         unsigned int type)
1823 {
1824         unsigned int len = 0;
1825
1826         while (len + 4 < ie_size) {
1827                 unsigned int hi = ie[len];
1828                 unsigned int lo = ie[len + 1];
1829                 unsigned int tmp_type = (hi << 8) + lo;
1830                 unsigned int v_len = 0;
1831
1832                 /* hi and lo are used to recreate an unsigned int
1833                  * based on 2 8bits length unsigned int. */
1834
1835                 hi = ie[len + 2];
1836                 lo = ie[len + 3];
1837                 v_len = (hi << 8) + lo;
1838
1839                 if (tmp_type == type) {
1840                         unsigned int ret_value = 0;
1841                         unsigned char *value = (unsigned char *)&ret_value;
1842
1843                         SUPPLICANT_DBG("IE: match type 0x%x", type);
1844
1845                         /* Verifying length relevance */
1846                         if (v_len > sizeof(unsigned int) ||
1847                                 len + 4 + v_len > ie_size)
1848                                 break;
1849
1850                         memcpy(value, ie + len + 4, v_len);
1851
1852                         SUPPLICANT_DBG("returning 0x%x", ret_value);
1853                         return ret_value;
1854                 }
1855
1856                 len += v_len + 4;
1857         }
1858
1859         SUPPLICANT_DBG("returning 0");
1860         return 0;
1861 }
1862
1863 static void bss_process_ies(DBusMessageIter *iter, void *user_data)
1864 {
1865         struct g_supplicant_bss *bss = user_data;
1866         const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
1867 #if defined TIZEN_EXT
1868         const unsigned char WIFI_OUI[] = {0x00, 0x16, 0x32};
1869 #endif
1870         unsigned char *ie, *ie_end;
1871         DBusMessageIter array;
1872         unsigned int value;
1873         int ie_len;
1874
1875 #define WMM_WPA1_WPS_INFO 221
1876 #define WPS_INFO_MIN_LEN  6
1877 #define WPS_VERSION_TLV   0x104A
1878 #define WPS_STATE_TLV     0x1044
1879 #define WPS_METHODS_TLV   0x1012
1880 #define WPS_REGISTRAR_TLV 0x1041
1881 #define WPS_VERSION       0x10
1882 #define WPS_PBC           0x04
1883 #define WPS_PIN           0x00
1884 #define WPS_CONFIGURED    0x02
1885 #if defined TIZEN_EXT
1886 #define VENDOR_SPECIFIC_INFO 0xDD
1887 #endif
1888
1889         dbus_message_iter_recurse(iter, &array);
1890         dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
1891
1892         if (!ie || ie_len < 2)
1893                 return;
1894
1895         bss->wps_capabilities = 0;
1896         bss->keymgmt = 0;
1897
1898         for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
1899                                                         ie += ie[1] + 2) {
1900 #if defined TIZEN_EXT
1901                 if((ie[0] == VENDOR_SPECIFIC_INFO) && (memcmp(ie+2, WIFI_OUI, sizeof(WIFI_OUI)) == 0)) {
1902                                 SUPPLICANT_DBG("IE: match WIFI_OUI");
1903                                 bss->wifi_vsie = (char *)g_try_malloc0(ie[1] + 2);   // tag number size(1), tag length size(1)
1904                                 if (bss->wifi_vsie) {
1905                                         bss->wifi_vsie_len = ie[1] + 2;
1906                                         memcpy(bss->wifi_vsie, ie, bss->wifi_vsie_len);
1907                                 } else {
1908                                         SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
1909                                 }
1910                                 continue;
1911                 }
1912 #endif
1913                 if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
1914                         memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
1915                         continue;
1916
1917                 SUPPLICANT_DBG("IE: match WPS_OUI");
1918
1919                 value = get_tlv(&ie[6], ie[1], WPS_STATE_TLV);
1920                 if (get_tlv(&ie[6], ie[1], WPS_VERSION_TLV) == WPS_VERSION &&
1921                                                                 value != 0) {
1922                         bss->keymgmt |= G_SUPPLICANT_KEYMGMT_WPS;
1923
1924                         if (value == WPS_CONFIGURED)
1925                                 bss->wps_capabilities |=
1926                                         G_SUPPLICANT_WPS_CONFIGURED;
1927                 }
1928
1929                 value = get_tlv(&ie[6], ie[1], WPS_METHODS_TLV);
1930                 if (value != 0) {
1931                         if (GUINT16_FROM_BE(value) == WPS_PBC)
1932                                 bss->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
1933                         if (GUINT16_FROM_BE(value) == WPS_PIN)
1934                                 bss->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
1935                 } else
1936                         bss->wps_capabilities |=
1937                                 G_SUPPLICANT_WPS_PBC | G_SUPPLICANT_WPS_PIN;
1938
1939                 /* If the AP sends this it means it's advertizing
1940                  * as a registrar and the WPS process is launched
1941                  * on its side */
1942                 if (get_tlv(&ie[6], ie[1], WPS_REGISTRAR_TLV) != 0)
1943                         bss->wps_capabilities |= G_SUPPLICANT_WPS_REGISTRAR;
1944
1945                 SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
1946         }
1947 }
1948
1949 static void bss_compute_security(struct g_supplicant_bss *bss)
1950 {
1951         /*
1952          * Combining RSN and WPA keymgmt
1953          * We combine it since parsing IEs might have set something for WPS. */
1954         bss->keymgmt |= bss->rsn_keymgmt | bss->wpa_keymgmt;
1955
1956         bss->ieee8021x = FALSE;
1957         bss->psk = FALSE;
1958 #if defined TIZEN_EXT
1959         bss->ft_ieee8021x = FALSE;
1960         bss->ft_psk = FALSE;
1961 #endif
1962
1963 #if defined TIZEN_EXT
1964         if (bss->keymgmt &
1965                         (G_SUPPLICANT_KEYMGMT_WPA_EAP |
1966                                         G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
1967                 bss->ieee8021x = TRUE;
1968         else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
1969                 bss->ft_ieee8021x = TRUE;
1970 #else
1971         if (bss->keymgmt &
1972                         (G_SUPPLICANT_KEYMGMT_WPA_EAP |
1973                                 G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
1974                                 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
1975                 bss->ieee8021x = TRUE;
1976 #endif
1977
1978 #if defined TIZEN_EXT
1979         if (bss->keymgmt &
1980                         (G_SUPPLICANT_KEYMGMT_WPA_PSK |
1981                                         G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
1982                 bss->psk = TRUE;
1983         else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
1984                 bss->ft_psk = TRUE;
1985 #else
1986         if (bss->keymgmt &
1987                         (G_SUPPLICANT_KEYMGMT_WPA_PSK |
1988                                 G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
1989                                 G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
1990                 bss->psk = TRUE;
1991 #endif
1992
1993         if (bss->ieee8021x)
1994                 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
1995         else if (bss->psk)
1996                 bss->security = G_SUPPLICANT_SECURITY_PSK;
1997 #if defined TIZEN_EXT
1998         else if (bss->ft_psk)
1999                 bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
2000         else if (bss->ft_ieee8021x == TRUE)
2001                 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
2002 #endif
2003         else if (bss->privacy)
2004                 bss->security = G_SUPPLICANT_SECURITY_WEP;
2005         else
2006                 bss->security = G_SUPPLICANT_SECURITY_NONE;
2007 }
2008
2009
2010 static void bss_property(const char *key, DBusMessageIter *iter,
2011                                                         void *user_data)
2012 {
2013         struct g_supplicant_bss *bss = user_data;
2014
2015         if (!bss->interface)
2016                 return;
2017
2018         SUPPLICANT_DBG("key %s", key);
2019
2020         if (!key)
2021                 return;
2022
2023         if (g_strcmp0(key, "BSSID") == 0) {
2024                 DBusMessageIter array;
2025                 unsigned char *addr;
2026                 int addr_len;
2027
2028                 dbus_message_iter_recurse(iter, &array);
2029                 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
2030
2031                 if (addr_len == 6)
2032                         memcpy(bss->bssid, addr, addr_len);
2033         } else if (g_strcmp0(key, "SSID") == 0) {
2034                 DBusMessageIter array;
2035                 unsigned char *ssid;
2036                 int ssid_len;
2037
2038                 dbus_message_iter_recurse(iter, &array);
2039                 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
2040
2041                 if (ssid_len > 0 && ssid_len < 33) {
2042                         memcpy(bss->ssid, ssid, ssid_len);
2043                         bss->ssid_len = ssid_len;
2044                 } else {
2045                         memset(bss->ssid, 0, sizeof(bss->ssid));
2046                         bss->ssid_len = 0;
2047                 }
2048         } else if (g_strcmp0(key, "Capabilities") == 0) {
2049                 dbus_uint16_t capabilities = 0x0000;
2050
2051                 dbus_message_iter_get_basic(iter, &capabilities);
2052
2053                 if (capabilities & IEEE80211_CAP_ESS)
2054                         bss->mode = G_SUPPLICANT_MODE_INFRA;
2055                 else if (capabilities & IEEE80211_CAP_IBSS)
2056                         bss->mode = G_SUPPLICANT_MODE_IBSS;
2057
2058                 if (capabilities & IEEE80211_CAP_PRIVACY)
2059                         bss->privacy = TRUE;
2060         } else if (g_strcmp0(key, "Mode") == 0) {
2061                 const char *mode = NULL;
2062
2063                 dbus_message_iter_get_basic(iter, &mode);
2064                 bss->mode = string2mode(mode);
2065         } else if (g_strcmp0(key, "Frequency") == 0) {
2066                 dbus_uint16_t frequency = 0;
2067
2068                 dbus_message_iter_get_basic(iter, &frequency);
2069                 bss->frequency = frequency;
2070         } else if (g_strcmp0(key, "Signal") == 0) {
2071                 dbus_int16_t signal = 0;
2072
2073                 dbus_message_iter_get_basic(iter, &signal);
2074
2075                 bss->signal = signal;
2076                 if (!bss->signal)
2077                         bss->signal = BSS_UNKNOWN_STRENGTH;
2078
2079         } else if (g_strcmp0(key, "Level") == 0) {
2080                 dbus_int32_t level = 0;
2081
2082                 dbus_message_iter_get_basic(iter, &level);
2083         } else if (g_strcmp0(key, "Rates") == 0) {
2084                 supplicant_dbus_array_foreach(iter, bss_rates, bss);
2085         } else if (g_strcmp0(key, "MaxRate") == 0) {
2086                 dbus_uint32_t maxrate = 0;
2087
2088                 dbus_message_iter_get_basic(iter, &maxrate);
2089                 if (maxrate != 0)
2090                         bss->maxrate = maxrate;
2091         } else if (g_strcmp0(key, "Privacy") == 0) {
2092                 dbus_bool_t privacy = FALSE;
2093
2094                 dbus_message_iter_get_basic(iter, &privacy);
2095                 bss->privacy = privacy;
2096         } else if (g_strcmp0(key, "RSN") == 0) {
2097                 bss->rsn_selected = TRUE;
2098
2099                 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
2100         } else if (g_strcmp0(key, "WPA") == 0) {
2101                 bss->rsn_selected = FALSE;
2102
2103                 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
2104         } else if (g_strcmp0(key, "IEs") == 0)
2105                 bss_process_ies(iter, bss);
2106         else
2107                 SUPPLICANT_DBG("key %s type %c",
2108                                 key, dbus_message_iter_get_arg_type(iter));
2109 }
2110
2111 static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
2112                                                         void *user_data)
2113 {
2114         GSupplicantInterface *interface = user_data;
2115         GSupplicantNetwork *network;
2116         struct g_supplicant_bss *bss;
2117         const char *path = NULL;
2118
2119         SUPPLICANT_DBG("");
2120
2121         dbus_message_iter_get_basic(iter, &path);
2122         if (!path)
2123                 return NULL;
2124
2125         if (g_strcmp0(path, "/") == 0)
2126                 return NULL;
2127
2128         SUPPLICANT_DBG("%s", path);
2129
2130         network = g_hash_table_lookup(interface->bss_mapping, path);
2131         if (network) {
2132                 bss = g_hash_table_lookup(network->bss_table, path);
2133                 if (bss)
2134                         return NULL;
2135         }
2136
2137         bss = g_try_new0(struct g_supplicant_bss, 1);
2138         if (!bss)
2139                 return NULL;
2140
2141         bss->interface = interface;
2142         bss->path = g_strdup(path);
2143         bss->signal = BSS_UNKNOWN_STRENGTH;
2144
2145         return bss;
2146 }
2147
2148 static void interface_bss_added_with_keys(DBusMessageIter *iter,
2149                                                 void *user_data)
2150 {
2151         struct g_supplicant_bss *bss;
2152
2153         SUPPLICANT_DBG("");
2154
2155         bss = interface_bss_added(iter, user_data);
2156         if (!bss)
2157                 return;
2158
2159         dbus_message_iter_next(iter);
2160
2161         if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID)
2162                 return;
2163
2164         supplicant_dbus_property_foreach(iter, bss_property, bss);
2165
2166         bss_compute_security(bss);
2167         add_or_replace_bss_to_network(bss);
2168 }
2169
2170 static void interface_bss_added_without_keys(DBusMessageIter *iter,
2171                                                 void *user_data)
2172 {
2173         struct g_supplicant_bss *bss;
2174
2175         SUPPLICANT_DBG("");
2176
2177         bss = interface_bss_added(iter, user_data);
2178         if (!bss)
2179                 return;
2180
2181         supplicant_dbus_property_get_all(bss->path,
2182                                         SUPPLICANT_INTERFACE ".BSS",
2183                                         bss_property, bss, NULL);
2184
2185         bss_compute_security(bss);
2186         add_or_replace_bss_to_network(bss);
2187 }
2188
2189 static void update_signal(gpointer key, gpointer value,
2190                                                 gpointer user_data)
2191 {
2192         struct g_supplicant_bss *bss = value;
2193         GSupplicantNetwork *network = user_data;
2194
2195         if (bss->signal > network->signal) {
2196                 network->signal = bss->signal;
2197                 network->best_bss = bss;
2198         }
2199 }
2200
2201 static void update_network_signal(GSupplicantNetwork *network)
2202 {
2203         if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
2204                 return;
2205
2206         g_hash_table_foreach(network->bss_table,
2207                                 update_signal, network);
2208
2209         SUPPLICANT_DBG("New network signal %d", network->signal);
2210 }
2211
2212 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
2213 {
2214         GSupplicantInterface *interface = user_data;
2215         GSupplicantNetwork *network;
2216         struct g_supplicant_bss *bss = NULL;
2217         const char *path = NULL;
2218
2219         dbus_message_iter_get_basic(iter, &path);
2220         if (!path)
2221                 return;
2222
2223         network = g_hash_table_lookup(interface->bss_mapping, path);
2224         if (!network)
2225                 return;
2226
2227         bss = g_hash_table_lookup(network->bss_table, path);
2228         if (network->best_bss == bss) {
2229                 network->best_bss = NULL;
2230                 network->signal = BSS_UNKNOWN_STRENGTH;
2231         }
2232
2233         g_hash_table_remove(bss_mapping, path);
2234
2235         g_hash_table_remove(interface->bss_mapping, path);
2236         g_hash_table_remove(network->bss_table, path);
2237
2238         update_network_signal(network);
2239
2240         if (g_hash_table_size(network->bss_table) == 0)
2241                 g_hash_table_remove(interface->network_table, network->group);
2242 }
2243
2244 static void set_config_methods(DBusMessageIter *iter, void *user_data)
2245 {
2246         const char *config_methods = "push_button";
2247
2248         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
2249                                                         &config_methods);
2250 }
2251
2252 static void interface_property(const char *key, DBusMessageIter *iter,
2253                                                         void *user_data)
2254 {
2255         GSupplicantInterface *interface = user_data;
2256
2257         if (!interface)
2258                 return;
2259
2260         SUPPLICANT_DBG("%s", key);
2261
2262         if (!key) {
2263                 debug_strvalmap("KeyMgmt capability", keymgmt_map,
2264                                                 interface->keymgmt_capa);
2265                 debug_strvalmap("AuthAlg capability", authalg_capa_map,
2266                                                 interface->authalg_capa);
2267                 debug_strvalmap("Protocol capability", proto_capa_map,
2268                                                 interface->proto_capa);
2269                 debug_strvalmap("Pairwise capability", pairwise_map,
2270                                                 interface->pairwise_capa);
2271                 debug_strvalmap("Group capability", group_map,
2272                                                 interface->group_capa);
2273                 debug_strvalmap("Scan capability", scan_capa_map,
2274                                                 interface->scan_capa);
2275                 debug_strvalmap("Mode capability", mode_capa_map,
2276                                                 interface->mode_capa);
2277
2278
2279                 supplicant_dbus_property_set(interface->path,
2280                                 SUPPLICANT_INTERFACE ".Interface.WPS",
2281                                 "ConfigMethods", DBUS_TYPE_STRING_AS_STRING,
2282                                 set_config_methods, NULL, NULL, NULL);
2283
2284                 if (interface->ready)
2285                         callback_interface_added(interface);
2286
2287                 return;
2288         }
2289
2290         if (g_strcmp0(key, "Capabilities") == 0) {
2291                 supplicant_dbus_property_foreach(iter, interface_capability,
2292                                                                 interface);
2293 #if !defined TIZEN_EXT
2294                 if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
2295                         interface->p2p_support = true;
2296 #endif
2297         } else if (g_strcmp0(key, "State") == 0) {
2298                 const char *str = NULL;
2299
2300                 dbus_message_iter_get_basic(iter, &str);
2301                 if (str)
2302                         if (string2state(str) != interface->state) {
2303                                 interface->state = string2state(str);
2304                                 callback_interface_state(interface);
2305                         }
2306                 if (interface->state == G_SUPPLICANT_STATE_DISABLED)
2307                         interface->ready = FALSE;
2308                 else
2309                         interface->ready = TRUE;
2310
2311                 SUPPLICANT_DBG("state %s (%d)", str, interface->state);
2312         } else if (g_strcmp0(key, "Scanning") == 0) {
2313                 dbus_bool_t scanning = FALSE;
2314
2315                 dbus_message_iter_get_basic(iter, &scanning);
2316                 interface->scanning = scanning;
2317
2318                 if (interface->ready) {
2319                         if (interface->scanning)
2320                                 callback_scan_started(interface);
2321                         else
2322                                 callback_scan_finished(interface);
2323                 }
2324         } else if (g_strcmp0(key, "ApScan") == 0) {
2325                 int apscan = 1;
2326
2327                 dbus_message_iter_get_basic(iter, &apscan);
2328                 interface->apscan = apscan;
2329         } else if (g_strcmp0(key, "Ifname") == 0) {
2330                 const char *str = NULL;
2331
2332                 dbus_message_iter_get_basic(iter, &str);
2333                 if (str) {
2334                         g_free(interface->ifname);
2335                         interface->ifname = g_strdup(str);
2336                 }
2337         } else if (g_strcmp0(key, "Driver") == 0) {
2338                 const char *str = NULL;
2339
2340                 dbus_message_iter_get_basic(iter, &str);
2341                 if (str) {
2342                         g_free(interface->driver);
2343                         interface->driver = g_strdup(str);
2344                 }
2345         } else if (g_strcmp0(key, "BridgeIfname") == 0) {
2346                 const char *str = NULL;
2347
2348                 dbus_message_iter_get_basic(iter, &str);
2349                 if (str) {
2350                         g_free(interface->bridge);
2351                         interface->bridge = g_strdup(str);
2352                 }
2353         } else if (g_strcmp0(key, "CurrentBSS") == 0) {
2354                 interface_bss_added_without_keys(iter, interface);
2355         } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
2356 #if defined TIZEN_EXT
2357                 if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
2358 #endif
2359                 interface_network_added(iter, interface);
2360         } else if (g_strcmp0(key, "BSSs") == 0) {
2361                 supplicant_dbus_array_foreach(iter,
2362                                         interface_bss_added_without_keys,
2363                                         interface);
2364         } else if (g_strcmp0(key, "Blobs") == 0) {
2365                 /* Nothing */
2366         } else if (g_strcmp0(key, "Networks") == 0) {
2367                 supplicant_dbus_array_foreach(iter, interface_network_added,
2368                                                                 interface);
2369         } else if (g_strcmp0(key, "DisconnectReason") == 0) {
2370                 int reason_code;
2371                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2372                         dbus_message_iter_get_basic(iter, &reason_code);
2373                         callback_disconnect_reason_code(interface, reason_code);
2374                 }
2375         } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
2376                 int status_code;
2377                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2378                         dbus_message_iter_get_basic(iter, &status_code);
2379                         callback_assoc_status_code(interface, status_code);
2380                 }
2381         } else
2382                 SUPPLICANT_DBG("key %s type %c",
2383                                 key, dbus_message_iter_get_arg_type(iter));
2384 }
2385
2386 static void scan_network_update(DBusMessageIter *iter, void *user_data)
2387 {
2388         GSupplicantInterface *interface = user_data;
2389         GSupplicantNetwork *network;
2390         char *path;
2391
2392         if (!iter)
2393                 return;
2394
2395         dbus_message_iter_get_basic(iter, &path);
2396
2397         if (!path)
2398                 return;
2399
2400         if (g_strcmp0(path, "/") == 0)
2401                 return;
2402
2403         /* Update the network details based on scan BSS data */
2404         network = g_hash_table_lookup(interface->bss_mapping, path);
2405         if (network)
2406                 callback_network_added(network);
2407 }
2408
2409 static void scan_bss_data(const char *key, DBusMessageIter *iter,
2410                                 void *user_data)
2411 {
2412         GSupplicantInterface *interface = user_data;
2413
2414 /*Fixed : stucking in scanning state when scan failed*/
2415 #if defined TIZEN_EXT
2416                 GSupplicantInterfaceCallback scan_callback;
2417 #endif
2418
2419         if (iter)
2420                 supplicant_dbus_array_foreach(iter, scan_network_update,
2421                                                 interface);
2422
2423 #if defined TIZEN_EXT
2424                 scan_callback = interface->scan_callback;
2425 #endif
2426
2427         if (interface->scan_callback)
2428                 interface->scan_callback(0, interface, interface->scan_data);
2429
2430 #if defined TIZEN_EXT
2431                 if (interface->scan_callback == scan_callback) {
2432 #endif
2433         interface->scan_callback = NULL;
2434         interface->scan_data = NULL;
2435 #if defined TIZEN_EXT
2436         }
2437 #endif
2438 }
2439
2440 static GSupplicantInterface *interface_alloc(const char *path)
2441 {
2442         GSupplicantInterface *interface;
2443
2444         interface = g_try_new0(GSupplicantInterface, 1);
2445         if (!interface)
2446                 return NULL;
2447
2448         interface->path = g_strdup(path);
2449
2450         interface->network_table = g_hash_table_new_full(g_str_hash,
2451                                         g_str_equal, NULL, remove_network);
2452         interface->peer_table = g_hash_table_new_full(g_str_hash,
2453                                         g_str_equal, NULL, remove_peer);
2454         interface->group_table = g_hash_table_new_full(g_str_hash,
2455                                         g_str_equal, NULL, remove_group);
2456         interface->net_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
2457                                                                 NULL, NULL);
2458         interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
2459                                                                 NULL, NULL);
2460
2461         g_hash_table_replace(interface_table, interface->path, interface);
2462
2463         return interface;
2464 }
2465
2466 static void interface_added(DBusMessageIter *iter, void *user_data)
2467 {
2468         GSupplicantInterface *interface;
2469         const char *path = NULL;
2470
2471         SUPPLICANT_DBG("");
2472
2473         dbus_message_iter_get_basic(iter, &path);
2474         if (!path)
2475                 return;
2476
2477         if (g_strcmp0(path, "/") == 0)
2478                 return;
2479
2480         interface = g_hash_table_lookup(interface_table, path);
2481         if (interface)
2482                 return;
2483
2484         interface = interface_alloc(path);
2485         if (!interface)
2486                 return;
2487
2488         dbus_message_iter_next(iter);
2489         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2490                 supplicant_dbus_property_foreach(iter, interface_property,
2491                                                                 interface);
2492                 interface_property(NULL, NULL, interface);
2493                 return;
2494         }
2495
2496         supplicant_dbus_property_get_all(path,
2497                                         SUPPLICANT_INTERFACE ".Interface",
2498                                         interface_property, interface,
2499                                         interface);
2500 }
2501
2502 static void interface_removed(DBusMessageIter *iter, void *user_data)
2503 {
2504         const char *path = NULL;
2505         GSupplicantInterface *interface = user_data;
2506
2507         dbus_message_iter_get_basic(iter, &path);
2508         if (!path)
2509                 return;
2510
2511         interface = g_hash_table_lookup(interface_table, path);
2512         g_supplicant_interface_cancel(interface);
2513
2514         g_hash_table_remove(interface_table, path);
2515 }
2516
2517 static void eap_method(DBusMessageIter *iter, void *user_data)
2518 {
2519         const char *str = NULL;
2520         int i;
2521
2522         dbus_message_iter_get_basic(iter, &str);
2523         if (!str)
2524                 return;
2525
2526         for (i = 0; eap_method_map[i].str; i++)
2527                 if (strcmp(str, eap_method_map[i].str) == 0) {
2528                         eap_methods |= eap_method_map[i].val;
2529                         break;
2530                 }
2531 }
2532
2533 static void service_property(const char *key, DBusMessageIter *iter,
2534                                                         void *user_data)
2535 {
2536         if (!key) {
2537                 callback_system_ready();
2538                 return;
2539         }
2540
2541         if (g_strcmp0(key, "DebugLevel") == 0) {
2542                 const char *str = NULL;
2543                 int i;
2544
2545                 dbus_message_iter_get_basic(iter, &str);
2546                 for (i = 0; debug_strings[i]; i++)
2547                         if (g_strcmp0(debug_strings[i], str) == 0) {
2548                                 debug_level = i;
2549                                 break;
2550                         }
2551                 SUPPLICANT_DBG("Debug level %d", debug_level);
2552         } else if (g_strcmp0(key, "DebugTimestamp") == 0) {
2553                 dbus_message_iter_get_basic(iter, &debug_timestamp);
2554                 SUPPLICANT_DBG("Debug timestamp %u", debug_timestamp);
2555         } else if (g_strcmp0(key, "DebugShowKeys") == 0) {
2556                 dbus_message_iter_get_basic(iter, &debug_showkeys);
2557                 SUPPLICANT_DBG("Debug show keys %u", debug_showkeys);
2558         } else if (g_strcmp0(key, "Interfaces") == 0) {
2559                 supplicant_dbus_array_foreach(iter, interface_added, NULL);
2560         } else if (g_strcmp0(key, "EapMethods") == 0) {
2561                 supplicant_dbus_array_foreach(iter, eap_method, NULL);
2562                 debug_strvalmap("EAP method", eap_method_map, eap_methods);
2563         } else if (g_strcmp0(key, "Country") == 0) {
2564                 const char *country = NULL;
2565
2566                 dbus_message_iter_get_basic(iter, &country);
2567                 SUPPLICANT_DBG("Country %s", country);
2568         } else
2569                 SUPPLICANT_DBG("key %s type %c",
2570                                 key, dbus_message_iter_get_arg_type(iter));
2571 }
2572
2573 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
2574 {
2575         const char *name = NULL, *old = NULL, *new = NULL;
2576
2577         SUPPLICANT_DBG("");
2578
2579         if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
2580                 return;
2581
2582         dbus_message_iter_get_basic(iter, &name);
2583         if (!name)
2584                 return;
2585
2586         if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
2587                 return;
2588
2589         dbus_message_iter_next(iter);
2590         dbus_message_iter_get_basic(iter, &old);
2591         dbus_message_iter_next(iter);
2592         dbus_message_iter_get_basic(iter, &new);
2593
2594         if (!old || !new)
2595                 return;
2596
2597         if (strlen(old) > 0 && strlen(new) == 0) {
2598                 system_available = FALSE;
2599                 g_hash_table_remove_all(bss_mapping);
2600                 g_hash_table_remove_all(peer_mapping);
2601                 g_hash_table_remove_all(group_mapping);
2602                 g_hash_table_remove_all(interface_table);
2603                 callback_system_killed();
2604         }
2605
2606         if (strlen(new) > 0 && strlen(old) == 0) {
2607                 system_available = TRUE;
2608                 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
2609                                                 SUPPLICANT_INTERFACE,
2610                                                 service_property, NULL, NULL);
2611         }
2612 }
2613
2614 static void signal_properties_changed(const char *path, DBusMessageIter *iter)
2615 {
2616         SUPPLICANT_DBG("");
2617
2618         if (g_strcmp0(path, SUPPLICANT_PATH) != 0)
2619                 return;
2620
2621         supplicant_dbus_property_foreach(iter, service_property, NULL);
2622 }
2623
2624 static void signal_interface_added(const char *path, DBusMessageIter *iter)
2625 {
2626         SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
2627
2628         if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
2629                 interface_added(iter, NULL);
2630 }
2631
2632 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
2633 {
2634         SUPPLICANT_DBG("");
2635
2636         if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
2637                 interface_removed(iter, NULL);
2638 }
2639
2640 static void signal_interface_changed(const char *path, DBusMessageIter *iter)
2641 {
2642         GSupplicantInterface *interface;
2643
2644         SUPPLICANT_DBG("");
2645
2646         interface = g_hash_table_lookup(interface_table, path);
2647         if (!interface)
2648                 return;
2649
2650         supplicant_dbus_property_foreach(iter, interface_property, interface);
2651 }
2652
2653 static void signal_scan_done(const char *path, DBusMessageIter *iter)
2654 {
2655         GSupplicantInterface *interface;
2656         dbus_bool_t success = FALSE;
2657
2658         SUPPLICANT_DBG("");
2659
2660         interface = g_hash_table_lookup(interface_table, path);
2661         if (!interface)
2662                 return;
2663
2664         dbus_message_iter_get_basic(iter, &success);
2665
2666         if (interface->scanning) {
2667                 callback_scan_finished(interface);
2668                 interface->scanning = FALSE;
2669         }
2670
2671         /*
2672          * If scan is unsuccessful return -EIO else get the scanned BSSs
2673          * and update the network details accordingly
2674          */
2675         if (!success) {
2676                 if (interface->scan_callback)
2677                         interface->scan_callback(-EIO, interface,
2678                                                 interface->scan_data);
2679
2680                 interface->scan_callback = NULL;
2681                 interface->scan_data = NULL;
2682
2683                 return;
2684         }
2685
2686         supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE ".Interface",
2687                                 "BSSs", scan_bss_data, interface, interface);
2688 }
2689
2690 static void signal_bss_added(const char *path, DBusMessageIter *iter)
2691 {
2692         GSupplicantInterface *interface;
2693
2694         SUPPLICANT_DBG("");
2695
2696         interface = g_hash_table_lookup(interface_table, path);
2697         if (!interface)
2698                 return;
2699
2700         interface_bss_added_with_keys(iter, interface);
2701 }
2702
2703 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
2704 {
2705         GSupplicantInterface *interface;
2706
2707         SUPPLICANT_DBG("");
2708
2709         interface = g_hash_table_lookup(interface_table, path);
2710         if (!interface)
2711                 return;
2712
2713         interface_bss_removed(iter, interface);
2714 }
2715
2716 static void signal_network_added(const char *path, DBusMessageIter *iter)
2717 {
2718         GSupplicantInterface *interface;
2719
2720         SUPPLICANT_DBG("");
2721
2722         interface = g_hash_table_lookup(interface_table, path);
2723         if (!interface)
2724                 return;
2725
2726         interface_network_added(iter, interface);
2727 }
2728
2729 static void signal_network_removed(const char *path, DBusMessageIter *iter)
2730 {
2731         GSupplicantInterface *interface;
2732
2733         SUPPLICANT_DBG("");
2734
2735         interface = g_hash_table_lookup(interface_table, path);
2736         if (!interface)
2737                 return;
2738
2739         interface_network_removed(iter, interface);
2740 }
2741
2742 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
2743 {
2744         GSupplicantInterface *interface;
2745         GSupplicantNetwork *network;
2746         GSupplicantSecurity old_security;
2747         struct g_supplicant_bss *bss;
2748
2749         SUPPLICANT_DBG("");
2750
2751         interface = g_hash_table_lookup(bss_mapping, path);
2752         if (!interface)
2753                 return;
2754
2755         network = g_hash_table_lookup(interface->bss_mapping, path);
2756         if (!network)
2757                 return;
2758
2759         bss = g_hash_table_lookup(network->bss_table, path);
2760         if (!bss)
2761                 return;
2762
2763         supplicant_dbus_property_foreach(iter, bss_property, bss);
2764 #if defined TIZEN_EXT
2765         network->frequency = bss->frequency;
2766 #endif
2767         old_security = network->security;
2768         bss_compute_security(bss);
2769
2770         if (old_security != bss->security) {
2771                 struct g_supplicant_bss *new_bss;
2772
2773                 SUPPLICANT_DBG("New network security for %s", bss->ssid);
2774
2775                 /* Security change policy:
2776                  * - we first copy the current bss into a new one with
2777                  * its own pointer (path)
2778                  * - we remove the current bss related network which will
2779                  * tell the plugin about such removal. This is done due
2780                  * to the fact that a security change means a group change
2781                  * so a complete network change.
2782                  * (current bss becomes invalid as well)
2783                  * - we add the new bss: it adds new network and tell the
2784                  * plugin about it. */
2785
2786                 new_bss = g_try_new0(struct g_supplicant_bss, 1);
2787                 if (!new_bss)
2788                         return;
2789
2790                 memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
2791                 new_bss->path = g_strdup(bss->path);
2792
2793                 g_hash_table_remove(interface->network_table, network->group);
2794
2795                 add_or_replace_bss_to_network(new_bss);
2796
2797                 return;
2798         }
2799
2800 #if defined TIZEN_EXT
2801         if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
2802                 network->wps = TRUE;
2803                 network->wps_capabilities |= bss->wps_capabilities;
2804         } else
2805                 network->wps = FALSE;
2806 #endif
2807
2808         if (bss->signal == network->signal)
2809 #ifndef TIZEN_EXT
2810                 return;
2811 #else
2812         {
2813                 callback_network_changed(network, "");
2814                 return;
2815         }
2816 #endif
2817
2818         /*
2819          * If the new signal is lower than the SSID signal, we need
2820          * to check for the new maximum.
2821          */
2822         if (bss->signal < network->signal) {
2823                 if (bss != network->best_bss)
2824 #ifndef TIZEN_EXT
2825                         return;
2826 #else
2827                 {
2828                         callback_network_changed(network, "");
2829                         return;
2830                 }
2831 #endif
2832                 network->signal = bss->signal;
2833                 update_network_signal(network);
2834         } else {
2835                 network->signal = bss->signal;
2836                 network->best_bss = bss;
2837         }
2838
2839         SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
2840                         network->signal);
2841
2842         callback_network_changed(network, "Signal");
2843 }
2844
2845 static void wps_credentials(const char *key, DBusMessageIter *iter,
2846                         void *user_data)
2847 {
2848         GSupplicantInterface *interface = user_data;
2849
2850         if (!key)
2851                 return;
2852
2853         SUPPLICANT_DBG("key %s", key);
2854
2855         if (g_strcmp0(key, "Key") == 0) {
2856                 DBusMessageIter array;
2857                 unsigned char *key_val;
2858                 int key_len;
2859
2860                 dbus_message_iter_recurse(iter, &array);
2861                 dbus_message_iter_get_fixed_array(&array, &key_val, &key_len);
2862
2863                 g_free(interface->wps_cred.key);
2864                 interface->wps_cred.key = g_try_malloc0(
2865                                                 sizeof(char) * key_len + 1);
2866
2867                 if (!interface->wps_cred.key)
2868                         return;
2869
2870                 memcpy(interface->wps_cred.key, key_val,
2871                                                 sizeof(char) * key_len);
2872
2873                 SUPPLICANT_DBG("WPS key present");
2874         } else if (g_strcmp0(key, "SSID") == 0) {
2875                 DBusMessageIter array;
2876                 unsigned char *ssid;
2877                 int ssid_len;
2878
2879                 dbus_message_iter_recurse(iter, &array);
2880                 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
2881
2882                 if (ssid_len > 0 && ssid_len < 33) {
2883                         memcpy(interface->wps_cred.ssid, ssid, ssid_len);
2884                         interface->wps_cred.ssid_len = ssid_len;
2885                 } else {
2886                         memset(interface->wps_cred.ssid, 0, 32);
2887                         interface->wps_cred.ssid_len = 0;
2888                 }
2889         }
2890 }
2891
2892 static void signal_wps_credentials(const char *path, DBusMessageIter *iter)
2893 {
2894         GSupplicantInterface *interface;
2895
2896         SUPPLICANT_DBG("");
2897
2898         interface = g_hash_table_lookup(interface_table, path);
2899         if (!interface)
2900                 return;
2901
2902         supplicant_dbus_property_foreach(iter, wps_credentials, interface);
2903 }
2904
2905 static void wps_event_args(const char *key, DBusMessageIter *iter,
2906                         void *user_data)
2907 {
2908         GSupplicantInterface *interface = user_data;
2909
2910         if (!key || !interface)
2911                 return;
2912
2913         SUPPLICANT_DBG("Arg Key %s", key);
2914 }
2915
2916 static void signal_wps_event(const char *path, DBusMessageIter *iter)
2917 {
2918         GSupplicantInterface *interface;
2919         const char *name = NULL;
2920
2921         SUPPLICANT_DBG("");
2922
2923         interface = g_hash_table_lookup(interface_table, path);
2924         if (!interface)
2925                 return;
2926
2927         dbus_message_iter_get_basic(iter, &name);
2928
2929         SUPPLICANT_DBG("Name: %s", name);
2930
2931         if (g_strcmp0(name, "success") == 0)
2932                 interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS;
2933         else if (g_strcmp0(name, "failed") == 0)
2934                 interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL;
2935         else
2936                 interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN;
2937
2938         if (!dbus_message_iter_has_next(iter))
2939                 return;
2940
2941         dbus_message_iter_next(iter);
2942
2943         supplicant_dbus_property_foreach(iter, wps_event_args, interface);
2944 }
2945
2946 #if defined TIZEN_EXT
2947 static void signal_power_off(const char *path, DBusMessageIter *iter)
2948 {
2949         int poweroff_state = 0;
2950
2951         dbus_message_iter_get_basic(iter, &poweroff_state);
2952
2953         SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
2954
2955         /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
2956         if (poweroff_state != 2 && poweroff_state != 3)
2957                 return;
2958
2959         if (callbacks_pointer == NULL)
2960                 return;
2961
2962         if (callbacks_pointer->system_power_off == NULL)
2963                 return;
2964
2965         callbacks_pointer->system_power_off();
2966 }
2967 #endif
2968
2969 static void signal_station_connected(const char *path, DBusMessageIter *iter)
2970 {
2971         GSupplicantInterface *interface;
2972         const char *sta_mac = NULL;
2973
2974         SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
2975
2976         if (callbacks_pointer->add_station == NULL)
2977                 return;
2978
2979         if (g_strcmp0(path, "/") == 0)
2980                 return;
2981
2982         interface = g_hash_table_lookup(interface_table, path);
2983         if (interface == NULL)
2984                 return;
2985
2986         dbus_message_iter_get_basic(iter, &sta_mac);
2987         if (sta_mac == NULL)
2988                 return;
2989
2990         SUPPLICANT_DBG("New station %s connected", sta_mac);
2991         callbacks_pointer->add_station(sta_mac);
2992 }
2993
2994 static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
2995 {
2996         GSupplicantInterface *interface;
2997         const char *sta_mac = NULL;
2998
2999         SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
3000
3001         if (callbacks_pointer->remove_station == NULL)
3002                 return;
3003
3004         if (g_strcmp0(path, "/") == 0)
3005                 return;
3006
3007         interface = g_hash_table_lookup(interface_table, path);
3008         if (interface == NULL)
3009                 return;
3010
3011         dbus_message_iter_get_basic(iter, &sta_mac);
3012         if (sta_mac == NULL)
3013                 return;
3014
3015         SUPPLICANT_DBG("Station %s disconnected", sta_mac);
3016         callbacks_pointer->remove_station(sta_mac);
3017 }
3018
3019 static void create_peer_identifier(GSupplicantPeer *peer)
3020 {
3021         const unsigned char test[ETH_ALEN] = {};
3022
3023         if (!peer)
3024                 return;
3025
3026         if (!memcmp(peer->device_address, test, ETH_ALEN)) {
3027                 peer->identifier = g_strdup(peer->name);
3028                 return;
3029         }
3030
3031         peer->identifier = g_malloc0(19);
3032         snprintf(peer->identifier, 19, "%02x%02x%02x%02x%02x%02x",
3033                                                 peer->device_address[0],
3034                                                 peer->device_address[1],
3035                                                 peer->device_address[2],
3036                                                 peer->device_address[3],
3037                                                 peer->device_address[4],
3038                                                 peer->device_address[5]);
3039 }
3040
3041 struct peer_property_data {
3042         GSupplicantPeer *peer;
3043         GSList *old_groups;
3044         bool groups_changed;
3045         bool services_changed;
3046 };
3047
3048 static void peer_groups_relation(DBusMessageIter *iter, void *user_data)
3049 {
3050         struct peer_property_data *data = user_data;
3051         GSupplicantPeer *peer = data->peer;
3052         GSupplicantGroup *group;
3053         const char *str = NULL;
3054         GSList *elem;
3055
3056         dbus_message_iter_get_basic(iter, &str);
3057         if (!str)
3058                 return;
3059
3060         group = g_hash_table_lookup(group_mapping, str);
3061         if (!group)
3062                 return;
3063
3064         elem = g_slist_find_custom(data->old_groups, str, g_str_equal);
3065         if (elem) {
3066                 data->old_groups = g_slist_remove_link(data->old_groups, elem);
3067                 peer->groups = g_slist_concat(elem, peer->groups);
3068         } else {
3069                 peer->groups = g_slist_prepend(peer->groups, g_strdup(str));
3070                 data->groups_changed = true;
3071         }
3072 }
3073
3074 static void peer_property(const char *key, DBusMessageIter *iter,
3075                                                         void *user_data)
3076 {
3077         GSupplicantPeer *pending_peer;
3078         struct peer_property_data *data = user_data;
3079         GSupplicantPeer *peer = data->peer;
3080
3081         SUPPLICANT_DBG("key: %s", key);
3082
3083         if (!peer->interface)
3084                 return;
3085
3086         if (!key) {
3087                 if (peer->name) {
3088                         create_peer_identifier(peer);
3089                         callback_peer_found(peer);
3090                         pending_peer = g_hash_table_lookup(
3091                                         pending_peer_connection, peer->path);
3092
3093                         if (pending_peer && pending_peer == peer) {
3094                                 callback_peer_request(peer);
3095                                 g_hash_table_remove(pending_peer_connection,
3096                                                 peer->path);
3097                         }
3098
3099                         dbus_free(data);
3100                 }
3101
3102                 return;
3103         }
3104
3105         if (g_strcmp0(key, "DeviceAddress") == 0) {
3106                 unsigned char *dev_addr;
3107                 DBusMessageIter array;
3108                 int len;
3109
3110                 dbus_message_iter_recurse(iter, &array);
3111                 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
3112
3113                 if (len == ETH_ALEN)
3114                         memcpy(peer->device_address, dev_addr, len);
3115         } else if (g_strcmp0(key, "DeviceName") == 0) {
3116                 const char *str = NULL;
3117
3118                 dbus_message_iter_get_basic(iter, &str);
3119                 if (str)
3120                         peer->name = g_strdup(str);
3121         } else if (g_strcmp0(key, "config_method") == 0) {
3122                 uint16_t wps_config;
3123
3124                 dbus_message_iter_get_basic(iter, &wps_config);
3125
3126                 if (wps_config & G_SUPPLICANT_WPS_CONFIG_PBC)
3127                         peer->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
3128                 if (wps_config & ~G_SUPPLICANT_WPS_CONFIG_PBC)
3129                         peer->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
3130         } else if (g_strcmp0(key, "Groups") == 0) {
3131                 data->old_groups = peer->groups;
3132                 peer->groups = NULL;
3133
3134                 supplicant_dbus_array_foreach(iter,
3135                                                 peer_groups_relation, data);
3136                 if (g_slist_length(data->old_groups) > 0) {
3137                         g_slist_free_full(data->old_groups, g_free);
3138                         data->groups_changed = true;
3139                 }
3140         } else if (g_strcmp0(key, "IEs") == 0) {
3141                 DBusMessageIter array;
3142                 unsigned char *ie;
3143                 int ie_len;
3144
3145                 dbus_message_iter_recurse(iter, &array);
3146                 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
3147
3148                 if (!ie || ie_len < 2)
3149                         return;
3150
3151                 if (peer->widi_ies) {
3152                         if (memcmp(peer->widi_ies, ie, ie_len) == 0)
3153                                 return;
3154
3155                         g_free(peer->widi_ies);
3156                         peer->widi_ies_length = 0;
3157                 }
3158
3159                 peer->widi_ies = g_malloc0(ie_len * sizeof(unsigned char));
3160
3161                 memcpy(peer->widi_ies, ie, ie_len);
3162                 peer->widi_ies_length = ie_len;
3163                 data->services_changed = true;
3164         }
3165 }
3166
3167 static void signal_peer_found(const char *path, DBusMessageIter *iter)
3168 {
3169         struct peer_property_data *property_data;
3170         GSupplicantInterface *interface;
3171         const char *obj_path = NULL;
3172         GSupplicantPeer *peer;
3173
3174         SUPPLICANT_DBG("");
3175
3176         interface = g_hash_table_lookup(interface_table, path);
3177         if (!interface)
3178                 return;
3179
3180         dbus_message_iter_get_basic(iter, &obj_path);
3181         if (!obj_path || g_strcmp0(obj_path, "/") == 0)
3182                 return;
3183
3184         peer = g_hash_table_lookup(interface->peer_table, obj_path);
3185         if (peer)
3186                 return;
3187
3188         peer = g_try_new0(GSupplicantPeer, 1);
3189         if (!peer)
3190                 return;
3191
3192         peer->interface = interface;
3193         peer->path = g_strdup(obj_path);
3194         g_hash_table_insert(interface->peer_table, peer->path, peer);
3195         g_hash_table_replace(peer_mapping, peer->path, interface);
3196
3197         property_data = dbus_malloc0(sizeof(struct peer_property_data));
3198         property_data->peer = peer;
3199
3200         dbus_message_iter_next(iter);
3201         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
3202                 supplicant_dbus_property_foreach(iter, peer_property,
3203                                                         property_data);
3204                 peer_property(NULL, NULL, property_data);
3205                 return;
3206         }
3207
3208         supplicant_dbus_property_get_all(obj_path,
3209                                         SUPPLICANT_INTERFACE ".Peer",
3210                                         peer_property, property_data, NULL);
3211 }
3212
3213 static void signal_peer_lost(const char *path, DBusMessageIter *iter)
3214 {
3215         GSupplicantInterface *interface;
3216         const char *obj_path = NULL;
3217         GSupplicantPeer *peer;
3218
3219         SUPPLICANT_DBG("");
3220
3221         interface = g_hash_table_lookup(interface_table, path);
3222         if (!interface)
3223                 return;
3224
3225         dbus_message_iter_get_basic(iter, &obj_path);
3226         if (!obj_path || g_strcmp0(obj_path, "/") == 0)
3227                 return;
3228
3229         peer = g_hash_table_lookup(interface->peer_table, obj_path);
3230         if (!peer)
3231                 return;
3232
3233         g_hash_table_remove(interface->peer_table, obj_path);
3234 }
3235
3236 static void signal_peer_changed(const char *path, DBusMessageIter *iter)
3237 {
3238         struct peer_property_data *property_data;
3239         GSupplicantInterface *interface;
3240         GSupplicantPeer *peer;
3241
3242         SUPPLICANT_DBG("");
3243
3244         interface = g_hash_table_lookup(peer_mapping, path);
3245         if (!interface)
3246                 return;
3247
3248         peer = g_hash_table_lookup(interface->peer_table, path);
3249         if (!peer) {
3250                 g_hash_table_remove(peer_mapping, path);
3251                 return;
3252         }
3253
3254         property_data = dbus_malloc0(sizeof(struct peer_property_data));
3255         property_data->peer = peer;
3256
3257         supplicant_dbus_property_foreach(iter, peer_property, property_data);
3258         if (property_data->services_changed)
3259                 callback_peer_changed(peer,
3260                                         G_SUPPLICANT_PEER_SERVICES_CHANGED);
3261
3262         if (property_data->groups_changed)
3263                 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_CHANGED);
3264
3265         dbus_free(property_data);
3266
3267         if (!g_supplicant_peer_is_in_a_group(peer))
3268                 peer->connection_requested = false;
3269 }
3270
3271 struct group_sig_data {
3272         const char *peer_obj_path;
3273         unsigned char iface_address[ETH_ALEN];
3274         const char *interface_obj_path;
3275         const char *group_obj_path;
3276         int role;
3277 };
3278
3279 static void group_sig_property(const char *key, DBusMessageIter *iter,
3280                                                         void *user_data)
3281 {
3282         struct group_sig_data *data = user_data;
3283
3284         if (!key)
3285                 return;
3286
3287         if (g_strcmp0(key, "peer_interface_addr") == 0) {
3288                 unsigned char *dev_addr;
3289                 DBusMessageIter array;
3290                 int len;
3291
3292                 dbus_message_iter_recurse(iter, &array);
3293                 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
3294
3295                 if (len == ETH_ALEN)
3296                         memcpy(data->iface_address, dev_addr, len);
3297         } else if (g_strcmp0(key, "role") == 0) {
3298                 const char *str = NULL;
3299
3300                 dbus_message_iter_get_basic(iter, &str);
3301                 if (g_strcmp0(str, "GO") == 0)
3302                         data->role = G_SUPPLICANT_GROUP_ROLE_GO;
3303                 else
3304                         data->role = G_SUPPLICANT_GROUP_ROLE_CLIENT;
3305         } else if (g_strcmp0(key, "peer_object") == 0)
3306                 dbus_message_iter_get_basic(iter, &data->peer_obj_path);
3307         else if (g_strcmp0(key, "interface_object") == 0)
3308                 dbus_message_iter_get_basic(iter, &data->interface_obj_path);
3309         else if (g_strcmp0(key, "group_object") == 0)
3310                 dbus_message_iter_get_basic(iter, &data->group_obj_path);
3311
3312 }
3313
3314 static void signal_group_success(const char *path, DBusMessageIter *iter)
3315 {
3316         GSupplicantInterface *interface;
3317         struct group_sig_data data = {};
3318         GSupplicantPeer *peer;
3319
3320         SUPPLICANT_DBG("");
3321
3322         interface = g_hash_table_lookup(interface_table, path);
3323         if (!interface)
3324                 return;
3325
3326         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3327         if (!data.peer_obj_path)
3328                 return;
3329
3330         peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
3331         if (!peer)
3332                 return;
3333
3334         memcpy(peer->iface_address, data.iface_address, ETH_ALEN);
3335         interface->pending_peer_path = peer->path;
3336 }
3337
3338 static void signal_group_failure(const char *path, DBusMessageIter *iter)
3339 {
3340         GSupplicantInterface *interface;
3341         struct group_sig_data data = {};
3342         GSupplicantPeer *peer;
3343
3344         SUPPLICANT_DBG("");
3345
3346         interface = g_hash_table_lookup(interface_table, path);
3347         if (!interface)
3348                 return;
3349
3350         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3351         if (!data.peer_obj_path)
3352                 return;
3353
3354         peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
3355         if (!peer)
3356                 return;
3357
3358         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_FAILED);
3359         peer->connection_requested = false;
3360 }
3361
3362 static void signal_group_started(const char *path, DBusMessageIter *iter)
3363 {
3364         GSupplicantInterface *interface, *g_interface;
3365         struct group_sig_data data = {};
3366         GSupplicantGroup *group;
3367         GSupplicantPeer *peer;
3368
3369         SUPPLICANT_DBG("");
3370
3371         interface = g_hash_table_lookup(interface_table, path);
3372         if (!interface)
3373                 return;
3374
3375         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3376         if (!data.interface_obj_path || !data.group_obj_path)
3377                 return;
3378
3379         peer = g_hash_table_lookup(interface->peer_table,
3380                                                 interface->pending_peer_path);
3381         interface->pending_peer_path = NULL;
3382         if (!peer)
3383                 return;
3384
3385         g_interface = g_hash_table_lookup(interface_table,
3386                                                 data.interface_obj_path);
3387         if (!g_interface)
3388                 return;
3389
3390         group = g_hash_table_lookup(interface->group_table,
3391                                                 data.group_obj_path);
3392         if (group)
3393                 return;
3394
3395         group = g_try_new0(GSupplicantGroup, 1);
3396         if (!group)
3397                 return;
3398
3399         group->interface = g_interface;
3400         group->orig_interface = interface;
3401         group->path = g_strdup(data.group_obj_path);
3402         group->role = data.role;
3403
3404         g_hash_table_insert(interface->group_table, group->path, group);
3405         g_hash_table_replace(group_mapping, group->path, group);
3406
3407         peer->current_group_iface = g_interface;
3408         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
3409 }
3410
3411 static void remove_peer_group_interface(GHashTable *group_table,
3412                                 const char* path)
3413 {
3414         GSupplicantGroup *group;
3415         GHashTableIter iter;
3416         gpointer value, key;
3417
3418         if (!group_table)
3419                 return;
3420
3421         group = g_hash_table_lookup(group_table, path);
3422
3423         if (!group || !group->orig_interface)
3424                 return;
3425
3426         g_hash_table_iter_init(&iter, group->orig_interface->peer_table);
3427
3428         while (g_hash_table_iter_next(&iter, &key, &value)) {
3429                 GSupplicantPeer *peer = value;
3430
3431                 if (peer->current_group_iface == group->interface)
3432                         peer->current_group_iface = NULL;
3433         }
3434 }
3435
3436 static void signal_group_finished(const char *path, DBusMessageIter *iter)
3437 {
3438         GSupplicantInterface *interface;
3439         struct group_sig_data data = {};
3440
3441         SUPPLICANT_DBG("");
3442
3443         interface = g_hash_table_lookup(interface_table, path);
3444         if (!interface)
3445                 return;
3446
3447         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3448         if (!data.interface_obj_path || !data.group_obj_path)
3449                 return;
3450
3451         remove_peer_group_interface(interface->group_table, data.group_obj_path);
3452
3453         g_hash_table_remove(group_mapping, data.group_obj_path);
3454
3455         g_hash_table_remove(interface->group_table, data.group_obj_path);
3456 }
3457
3458 static void signal_group_request(const char *path, DBusMessageIter *iter)
3459 {
3460         GSupplicantInterface *interface;
3461         GSupplicantPeer *peer;
3462         const char *obj_path;
3463
3464         SUPPLICANT_DBG("");
3465
3466         interface = g_hash_table_lookup(interface_table, path);
3467         if (!interface)
3468                 return;
3469
3470         dbus_message_iter_get_basic(iter, &obj_path);
3471         if (!obj_path || !g_strcmp0(obj_path, "/"))
3472                 return;
3473
3474         peer = g_hash_table_lookup(interface->peer_table, obj_path);
3475         if (!peer)
3476                 return;
3477
3478         /*
3479          * Peer has been previously found and property set,
3480          * otherwise, defer connection to when peer property
3481          * is set.
3482          */
3483         if (peer->identifier)
3484                 callback_peer_request(peer);
3485         else
3486                 g_hash_table_replace(pending_peer_connection, peer->path, peer);
3487 }
3488
3489 static void signal_group_peer_joined(const char *path, DBusMessageIter *iter)
3490 {
3491         const char *peer_path = NULL;
3492         GSupplicantInterface *interface;
3493         GSupplicantGroup *group;
3494         GSupplicantPeer *peer;
3495
3496         SUPPLICANT_DBG("");
3497
3498         group = g_hash_table_lookup(group_mapping, path);
3499         if (!group)
3500                 return;
3501
3502         dbus_message_iter_get_basic(iter, &peer_path);
3503         if (!peer_path)
3504                 return;
3505
3506         interface = g_hash_table_lookup(peer_mapping, peer_path);
3507         if (!interface)
3508                 return;
3509
3510         peer = g_hash_table_lookup(interface->peer_table, peer_path);
3511         if (!peer)
3512                 return;
3513
3514         group->members = g_slist_prepend(group->members, g_strdup(peer_path));
3515
3516         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_JOINED);
3517 }
3518
3519 static void signal_group_peer_disconnected(const char *path, DBusMessageIter *iter)
3520 {
3521         const char *peer_path = NULL;
3522         GSupplicantInterface *interface;
3523         GSupplicantGroup *group;
3524         GSupplicantPeer *peer;
3525         GSList *elem;
3526
3527         SUPPLICANT_DBG("");
3528
3529         group = g_hash_table_lookup(group_mapping, path);
3530         if (!group)
3531                 return;
3532
3533         dbus_message_iter_get_basic(iter, &peer_path);
3534         if (!peer_path)
3535                 return;
3536
3537         for (elem = group->members; elem; elem = elem->next) {
3538                 if (!g_strcmp0(elem->data, peer_path))
3539                         break;
3540         }
3541
3542         if (!elem)
3543                 return;
3544
3545         g_free(elem->data);
3546         group->members = g_slist_delete_link(group->members, elem);
3547
3548         interface = g_hash_table_lookup(peer_mapping, peer_path);
3549         if (!interface)
3550                 return;
3551
3552         peer = g_hash_table_lookup(interface->peer_table, peer_path);
3553         if (!peer)
3554                 return;
3555
3556         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
3557         peer->connection_requested = false;
3558 }
3559
3560 static struct {
3561         const char *interface;
3562         const char *member;
3563         void (*function) (const char *path, DBusMessageIter *iter);
3564 } signal_map[] = {
3565         { DBUS_INTERFACE_DBUS,  "NameOwnerChanged",  signal_name_owner_changed },
3566
3567         { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
3568         { SUPPLICANT_INTERFACE, "InterfaceAdded",    signal_interface_added    },
3569         { SUPPLICANT_INTERFACE, "InterfaceCreated",  signal_interface_added    },
3570         { SUPPLICANT_INTERFACE, "InterfaceRemoved",  signal_interface_removed  },
3571
3572         { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
3573         { SUPPLICANT_INTERFACE ".Interface", "ScanDone",          signal_scan_done         },
3574         { SUPPLICANT_INTERFACE ".Interface", "BSSAdded",          signal_bss_added         },
3575         { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",        signal_bss_removed       },
3576         { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",      signal_network_added     },
3577         { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",    signal_network_removed   },
3578
3579         { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed   },
3580
3581         { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
3582         { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
3583 #if defined TIZEN_EXT
3584         { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
3585 #endif
3586
3587         { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected      },
3588         { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected },
3589
3590         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
3591         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
3592
3593         { SUPPLICANT_INTERFACE ".Peer", "PropertiesChanged", signal_peer_changed },
3594
3595         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", signal_group_success },
3596         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", signal_group_failure },
3597         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", signal_group_started },
3598         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished },
3599         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request },
3600
3601         { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
3602         { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
3603
3604         { }
3605 };
3606
3607 static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
3608                                         DBusMessage *message, void *data)
3609 {
3610         DBusMessageIter iter;
3611         const char *path;
3612         int i;
3613
3614         path = dbus_message_get_path(message);
3615         if (!path)
3616                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3617
3618         if (!dbus_message_iter_init(message, &iter))
3619                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3620
3621         for (i = 0; signal_map[i].interface; i++) {
3622                 if (!dbus_message_has_interface(message, signal_map[i].interface))
3623                         continue;
3624
3625                 if (!dbus_message_has_member(message, signal_map[i].member))
3626                         continue;
3627
3628                 signal_map[i].function(path, &iter);
3629                 break;
3630         }
3631
3632         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3633 }
3634
3635 void g_supplicant_interface_cancel(GSupplicantInterface *interface)
3636 {
3637         SUPPLICANT_DBG("Cancelling any pending DBus calls");
3638         supplicant_dbus_method_call_cancel_all(interface);
3639         supplicant_dbus_property_call_cancel_all(interface);
3640 }
3641
3642 struct supplicant_regdom {
3643         GSupplicantCountryCallback callback;
3644         const char *alpha2;
3645         const void *user_data;
3646 };
3647
3648 static void country_result(const char *error,
3649                                 DBusMessageIter *iter, void *user_data)
3650 {
3651         struct supplicant_regdom *regdom = user_data;
3652         int result = 0;
3653
3654         SUPPLICANT_DBG("Country setting result");
3655
3656         if (!user_data)
3657                 return;
3658
3659         if (error) {
3660                 SUPPLICANT_DBG("Country setting failure %s", error);
3661                 result = -EINVAL;
3662         }
3663
3664         if (regdom->callback)
3665                 regdom->callback(result, regdom->alpha2,
3666                                         (void *) regdom->user_data);
3667
3668         g_free(regdom);
3669 }
3670
3671 static void country_params(DBusMessageIter *iter, void *user_data)
3672 {
3673         struct supplicant_regdom *regdom = user_data;
3674
3675         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
3676                                                         &regdom->alpha2);
3677 }
3678
3679 int g_supplicant_set_country(const char *alpha2,
3680                                 GSupplicantCountryCallback callback,
3681                                         const void *user_data)
3682 {
3683         struct supplicant_regdom *regdom;
3684
3685         SUPPLICANT_DBG("Country setting %s", alpha2);
3686
3687         if (!system_available)
3688                 return -EFAULT;
3689
3690         regdom = dbus_malloc0(sizeof(*regdom));
3691         if (!regdom)
3692                 return -ENOMEM;
3693
3694         regdom->callback = callback;
3695         regdom->alpha2 = alpha2;
3696         regdom->user_data = user_data;
3697
3698         return supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
3699                                         "Country", DBUS_TYPE_STRING_AS_STRING,
3700                                         country_params, country_result,
3701                                         regdom, NULL);
3702 }
3703
3704 int g_supplicant_interface_set_country(GSupplicantInterface *interface,
3705                                         GSupplicantCountryCallback callback,
3706                                                         const char *alpha2,
3707                                                         void *user_data)
3708 {
3709         struct supplicant_regdom *regdom;
3710
3711         regdom = dbus_malloc0(sizeof(*regdom));
3712         if (!regdom)
3713                 return -ENOMEM;
3714
3715         regdom->callback = callback;
3716         regdom->alpha2 = alpha2;
3717         regdom->user_data = user_data;
3718
3719         return supplicant_dbus_property_set(interface->path,
3720                                 SUPPLICANT_INTERFACE ".Interface",
3721                                 "Country", DBUS_TYPE_STRING_AS_STRING,
3722                                 country_params, country_result,
3723                                         regdom, NULL);
3724 }
3725
3726 bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface)
3727 {
3728         if (!interface)
3729                 return false;
3730
3731         return interface->p2p_support;
3732 }
3733
3734 struct supplicant_p2p_dev_config {
3735         char *device_name;
3736         char *dev_type;
3737 };
3738
3739 static void p2p_device_config_result(const char *error,
3740                                         DBusMessageIter *iter, void *user_data)
3741 {
3742         struct supplicant_p2p_dev_config *config = user_data;
3743
3744         if (error)
3745                 SUPPLICANT_DBG("Unable to set P2P Device configuration: %s",
3746                                                                         error);
3747
3748         g_free(config->device_name);
3749         g_free(config->dev_type);
3750         dbus_free(config);
3751 }
3752
3753 static int dev_type_str2bin(const char *type, unsigned char dev_type[8])
3754 {
3755         int length, pos, end;
3756         char b[3] = {};
3757         char *e = NULL;
3758
3759         end = strlen(type);
3760         for (length = pos = 0; type[pos] != '\0' && length < 8; length++) {
3761                 if (pos+2 > end)
3762                         return 0;
3763
3764                 b[0] = type[pos];
3765                 b[1] = type[pos+1];
3766
3767                 dev_type[length] = strtol(b, &e, 16);
3768                 if (e && *e != '\0')
3769                         return 0;
3770
3771                 pos += 2;
3772         }
3773
3774         return 8;
3775 }
3776
3777 static void p2p_device_config_params(DBusMessageIter *iter, void *user_data)
3778 {
3779         struct supplicant_p2p_dev_config *config = user_data;
3780         DBusMessageIter dict;
3781
3782         supplicant_dbus_dict_open(iter, &dict);
3783
3784         supplicant_dbus_dict_append_basic(&dict, "DeviceName",
3785                                 DBUS_TYPE_STRING, &config->device_name);
3786
3787         if (config->dev_type) {
3788                 unsigned char dev_type[8] = {}, *type;
3789                 int len;
3790
3791                 len = dev_type_str2bin(config->dev_type, dev_type);
3792                 if (len) {
3793                         type = dev_type;
3794                         supplicant_dbus_dict_append_fixed_array(&dict,
3795                                         "PrimaryDeviceType",
3796                                         DBUS_TYPE_BYTE, &type, len);
3797                 }
3798         }
3799
3800         supplicant_dbus_dict_close(iter, &dict);
3801 }
3802
3803 int g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface,
3804                                         const char *device_name,
3805                                         const char *primary_dev_type)
3806 {
3807         struct supplicant_p2p_dev_config *config;
3808         int ret;
3809
3810         SUPPLICANT_DBG("P2P Device settings %s/%s",
3811                                         device_name, primary_dev_type);
3812
3813         config = dbus_malloc0(sizeof(*config));
3814         if (!config)
3815                 return -ENOMEM;
3816
3817         config->device_name = g_strdup(device_name);
3818         config->dev_type = g_strdup(primary_dev_type);
3819
3820         ret = supplicant_dbus_property_set(interface->path,
3821                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
3822                                 "P2PDeviceConfig",
3823                                 DBUS_TYPE_ARRAY_AS_STRING
3824                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3825                                 DBUS_TYPE_STRING_AS_STRING
3826                                 DBUS_TYPE_VARIANT_AS_STRING
3827                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
3828                                 p2p_device_config_params,
3829                                 p2p_device_config_result, config, NULL);
3830         if (ret < 0) {
3831                 g_free(config->device_name);
3832                 g_free(config->dev_type);
3833                 dbus_free(config);
3834                 SUPPLICANT_DBG("Unable to set P2P Device configuration");
3835         }
3836
3837         return ret;
3838 }
3839
3840 static gboolean peer_lookup_by_identifier(gpointer key, gpointer value,
3841                                                         gpointer user_data)
3842 {
3843         const GSupplicantPeer *peer = value;
3844         const char *identifier = user_data;
3845
3846         if (!g_strcmp0(identifier, peer->identifier))
3847                 return TRUE;
3848
3849         return FALSE;
3850 }
3851
3852 GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interface,
3853                                                         const char *identifier)
3854 {
3855         GSupplicantPeer *peer;
3856
3857         peer = g_hash_table_find(interface->peer_table,
3858                                         peer_lookup_by_identifier,
3859                                         (void *) identifier);
3860         return peer;
3861 }
3862
3863 struct interface_data {
3864         GSupplicantInterface *interface;
3865         char *path; /* Interface path cannot be taken from interface (above) as
3866                      * it might have been freed already.
3867                      */
3868         GSupplicantInterfaceCallback callback;
3869         void *user_data;
3870 };
3871
3872 struct interface_create_data {
3873         char *ifname;
3874         char *driver;
3875         char *bridge;
3876         GSupplicantInterface *interface;
3877         GSupplicantInterfaceCallback callback;
3878         void *user_data;
3879 };
3880
3881 struct interface_connect_data {
3882         GSupplicantInterface *interface;
3883         char *path;
3884         GSupplicantInterfaceCallback callback;
3885         union {
3886                 GSupplicantSSID *ssid;
3887                 GSupplicantPeerParams *peer;
3888         };
3889         void *user_data;
3890 };
3891
3892 struct interface_scan_data {
3893         GSupplicantInterface *interface;
3894         char *path;
3895         GSupplicantInterfaceCallback callback;
3896         GSupplicantScanParams *scan_params;
3897         void *user_data;
3898 };
3899
3900 static void interface_create_data_free(struct interface_create_data *data)
3901 {
3902         g_free(data->ifname);
3903         g_free(data->driver);
3904         g_free(data->bridge);
3905         dbus_free(data);
3906 }
3907
3908 static bool interface_exists(GSupplicantInterface *interface,
3909                                 const char *path)
3910 {
3911         GSupplicantInterface *tmp;
3912
3913         tmp = g_hash_table_lookup(interface_table, path);
3914         if (tmp && tmp == interface)
3915                 return true;
3916
3917         return false;
3918 }
3919
3920 static void interface_create_property(const char *key, DBusMessageIter *iter,
3921                                                         void *user_data)
3922 {
3923         struct interface_create_data *data = user_data;
3924         GSupplicantInterface *interface = data->interface;
3925
3926         if (!key) {
3927                 if (data->callback) {
3928                         data->callback(0, data->interface, data->user_data);
3929 #if !defined TIZEN_EXT
3930                         callback_p2p_support(interface);
3931 #endif
3932                 }
3933
3934                 interface_create_data_free(data);
3935         }
3936
3937         interface_property(key, iter, interface);
3938 }
3939
3940 static void interface_create_result(const char *error,
3941                                 DBusMessageIter *iter, void *user_data)
3942 {
3943         struct interface_create_data *data = user_data;
3944         const char *path = NULL;
3945         int err;
3946
3947         SUPPLICANT_DBG("");
3948
3949         if (error) {
3950                 g_warning("error %s", error);
3951                 err = -EIO;
3952                 goto done;
3953         }
3954
3955         dbus_message_iter_get_basic(iter, &path);
3956         if (!path) {
3957                 err = -EINVAL;
3958                 goto done;
3959         }
3960
3961         if (!system_available) {
3962                 err = -EFAULT;
3963                 goto done;
3964         }
3965
3966         data->interface = g_hash_table_lookup(interface_table, path);
3967         if (!data->interface) {
3968                 data->interface = interface_alloc(path);
3969                 if (!data->interface) {
3970                         err = -ENOMEM;
3971                         goto done;
3972                 }
3973         }
3974
3975         err = supplicant_dbus_property_get_all(path,
3976                                         SUPPLICANT_INTERFACE ".Interface",
3977                                         interface_create_property, data,
3978                                         NULL);
3979         if (err == 0)
3980                 return;
3981
3982 done:
3983         if (data->callback)
3984                 data->callback(err, NULL, data->user_data);
3985
3986         interface_create_data_free(data);
3987 }
3988
3989 static void interface_create_params(DBusMessageIter *iter, void *user_data)
3990 {
3991         struct interface_create_data *data = user_data;
3992         DBusMessageIter dict;
3993
3994         SUPPLICANT_DBG("");
3995
3996         supplicant_dbus_dict_open(iter, &dict);
3997
3998         supplicant_dbus_dict_append_basic(&dict, "Ifname",
3999                                         DBUS_TYPE_STRING, &data->ifname);
4000
4001         if (data->driver)
4002                 supplicant_dbus_dict_append_basic(&dict, "Driver",
4003                                         DBUS_TYPE_STRING, &data->driver);
4004
4005         if (data->bridge)
4006                 supplicant_dbus_dict_append_basic(&dict, "BridgeIfname",
4007                                         DBUS_TYPE_STRING, &data->bridge);
4008
4009         supplicant_dbus_dict_close(iter, &dict);
4010 }
4011
4012 static void interface_get_result(const char *error,
4013                                 DBusMessageIter *iter, void *user_data)
4014 {
4015         struct interface_create_data *data = user_data;
4016         GSupplicantInterface *interface;
4017         const char *path = NULL;
4018         int err;
4019
4020         SUPPLICANT_DBG("");
4021
4022         if (error) {
4023                 SUPPLICANT_DBG("Interface not created yet");
4024                 goto create;
4025         }
4026
4027         dbus_message_iter_get_basic(iter, &path);
4028         if (!path) {
4029                 err = -EINVAL;
4030                 goto done;
4031         }
4032
4033         interface = g_hash_table_lookup(interface_table, path);
4034         if (!interface) {
4035                 err = -ENOENT;
4036                 goto done;
4037         }
4038
4039         if (data->callback) {
4040                 data->callback(0, interface, data->user_data);
4041 #if !defined TIZEN_EXT
4042                 callback_p2p_support(interface);
4043 #endif
4044         }
4045
4046         interface_create_data_free(data);
4047
4048         return;
4049
4050 create:
4051         if (!system_available) {
4052                 err = -EFAULT;
4053                 goto done;
4054         }
4055
4056         SUPPLICANT_DBG("Creating interface");
4057
4058         err = supplicant_dbus_method_call(SUPPLICANT_PATH,
4059                                                 SUPPLICANT_INTERFACE,
4060                                                 "CreateInterface",
4061                                                 interface_create_params,
4062                                                 interface_create_result, data,
4063                                                 NULL);
4064         if (err == 0)
4065                 return;
4066
4067 done:
4068         if (data->callback)
4069                 data->callback(err, NULL, data->user_data);
4070
4071         interface_create_data_free(data);
4072 }
4073
4074 static void interface_get_params(DBusMessageIter *iter, void *user_data)
4075 {
4076         struct interface_create_data *data = user_data;
4077
4078         SUPPLICANT_DBG("");
4079
4080         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
4081 }
4082
4083 int g_supplicant_interface_create(const char *ifname, const char *driver,
4084                                         const char *bridge,
4085                                         GSupplicantInterfaceCallback callback,
4086                                                         void *user_data)
4087 {
4088         struct interface_create_data *data;
4089         int ret;
4090
4091         SUPPLICANT_DBG("ifname %s", ifname);
4092
4093         if (!ifname)
4094                 return -EINVAL;
4095
4096         if (!system_available)
4097                 return -EFAULT;
4098
4099         data = dbus_malloc0(sizeof(*data));
4100         if (!data)
4101                 return -ENOMEM;
4102
4103         data->ifname = g_strdup(ifname);
4104         data->driver = g_strdup(driver);
4105         data->bridge = g_strdup(bridge);
4106         data->callback = callback;
4107         data->user_data = user_data;
4108
4109         ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
4110                                                 SUPPLICANT_INTERFACE,
4111                                                 "GetInterface",
4112                                                 interface_get_params,
4113                                                 interface_get_result, data,
4114                                                 NULL);
4115         if (ret < 0)
4116                 interface_create_data_free(data);
4117
4118         return ret;
4119 }
4120
4121 static void interface_remove_result(const char *error,
4122                                 DBusMessageIter *iter, void *user_data)
4123 {
4124         struct interface_data *data = user_data;
4125         int err;
4126
4127         if (error) {
4128                 err = -EIO;
4129                 goto done;
4130         }
4131
4132         if (!system_available) {
4133                 err = -EFAULT;
4134                 goto done;
4135         }
4136
4137         /*
4138          * The gsupplicant interface is already freed by the InterfaceRemoved
4139          * signal callback. Simply invoke the interface_data callback.
4140          */
4141         err = 0;
4142
4143 done:
4144         g_free(data->path);
4145
4146         if (data->callback)
4147                 data->callback(err, NULL, data->user_data);
4148
4149         dbus_free(data);
4150 }
4151
4152
4153 static void interface_remove_params(DBusMessageIter *iter, void *user_data)
4154 {
4155         struct interface_data *data = user_data;
4156
4157         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
4158                                                         &data->interface->path);
4159 }
4160
4161
4162 int g_supplicant_interface_remove(GSupplicantInterface *interface,
4163                         GSupplicantInterfaceCallback callback,
4164                                                         void *user_data)
4165 {
4166         struct interface_data *data;
4167         int ret;
4168
4169         if (!interface)
4170                 return -EINVAL;
4171
4172         if (!system_available)
4173                 return -EFAULT;
4174
4175         g_supplicant_interface_cancel(interface);
4176
4177         data = dbus_malloc0(sizeof(*data));
4178         if (!data)
4179                 return -ENOMEM;
4180
4181         data->interface = interface;
4182         data->path = g_strdup(interface->path);
4183         data->callback = callback;
4184         data->user_data = user_data;
4185
4186         ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
4187                                                 SUPPLICANT_INTERFACE,
4188                                                 "RemoveInterface",
4189                                                 interface_remove_params,
4190                                                 interface_remove_result, data,
4191                                                 NULL);
4192         if (ret < 0) {
4193                 g_free(data->path);
4194                 dbus_free(data);
4195         }
4196         return ret;
4197 }
4198
4199 static void interface_scan_result(const char *error,
4200                                 DBusMessageIter *iter, void *user_data)
4201 {
4202         struct interface_scan_data *data = user_data;
4203         int err = 0;
4204
4205         if (error) {
4206                 SUPPLICANT_DBG("error %s", error);
4207                 err = -EIO;
4208         }
4209
4210         /* A non ready interface cannot send/receive anything */
4211         if (interface_exists(data->interface, data->path)) {
4212                 if (!data->interface->ready)
4213                         err = -ENOLINK;
4214         }
4215
4216         g_free(data->path);
4217
4218         if (err != 0) {
4219                 if (data->callback)
4220                         data->callback(err, data->interface, data->user_data);
4221         } else {
4222                 data->interface->scan_callback = data->callback;
4223                 data->interface->scan_data = data->user_data;
4224         }
4225
4226         if (data->scan_params)
4227                 g_supplicant_free_scan_params(data->scan_params);
4228
4229         dbus_free(data);
4230 }
4231
4232 static void add_scan_frequency(DBusMessageIter *iter, unsigned int freq)
4233 {
4234         DBusMessageIter data;
4235         unsigned int width = 0; /* Not used by wpa_supplicant atm */
4236
4237         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &data);
4238
4239         dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &freq);
4240         dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &width);
4241
4242         dbus_message_iter_close_container(iter, &data);
4243 }
4244
4245 static void add_scan_frequencies(DBusMessageIter *iter,
4246                                                 void *user_data)
4247 {
4248         GSupplicantScanParams *scan_data = user_data;
4249         unsigned int freq;
4250         int i;
4251
4252         for (i = 0; i < scan_data->num_freqs; i++) {
4253                 freq = scan_data->freqs[i];
4254                 if (!freq)
4255                         break;
4256
4257                 add_scan_frequency(iter, freq);
4258         }
4259 }
4260
4261 static void append_ssid(DBusMessageIter *iter,
4262                         const void *ssid, unsigned int len)
4263 {
4264         DBusMessageIter array;
4265
4266         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
4267         DBUS_TYPE_BYTE_AS_STRING, &array);
4268
4269         dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
4270                                                                 &ssid, len);
4271         dbus_message_iter_close_container(iter, &array);
4272 }
4273
4274 static void append_ssids(DBusMessageIter *iter, void *user_data)
4275 {
4276         GSupplicantScanParams *scan_data = user_data;
4277         GSList *list;
4278
4279         for (list = scan_data->ssids; list; list = list->next) {
4280                 struct scan_ssid *scan_ssid = list->data;
4281
4282                 append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
4283         }
4284 }
4285
4286 static void supplicant_add_scan_frequency(DBusMessageIter *dict,
4287                 supplicant_dbus_array_function function,
4288                                         void *user_data)
4289 {
4290         GSupplicantScanParams *scan_params = user_data;
4291         DBusMessageIter entry, value, array;
4292         const char *key = "Channels";
4293
4294         if (scan_params->freqs && scan_params->freqs[0] != 0) {
4295                 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
4296                                                 NULL, &entry);
4297
4298                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
4299
4300                 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
4301                                         DBUS_TYPE_ARRAY_AS_STRING
4302                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
4303                                         DBUS_TYPE_UINT32_AS_STRING
4304                                         DBUS_TYPE_UINT32_AS_STRING
4305                                         DBUS_STRUCT_END_CHAR_AS_STRING,
4306                                         &value);
4307
4308                 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
4309                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
4310                                         DBUS_TYPE_UINT32_AS_STRING
4311                                         DBUS_TYPE_UINT32_AS_STRING
4312                                         DBUS_STRUCT_END_CHAR_AS_STRING,
4313                                         &array);
4314
4315                 if (function)
4316                         function(&array, user_data);
4317
4318                 dbus_message_iter_close_container(&value, &array);
4319                 dbus_message_iter_close_container(&entry, &value);
4320                 dbus_message_iter_close_container(dict, &entry);
4321         }
4322 }
4323
4324 static void interface_scan_params(DBusMessageIter *iter, void *user_data)
4325 {
4326         DBusMessageIter dict;
4327         const char *type = "passive";
4328         struct interface_scan_data *data = user_data;
4329
4330         supplicant_dbus_dict_open(iter, &dict);
4331
4332         if (data && data->scan_params) {
4333                 type = "active";
4334
4335                 supplicant_dbus_dict_append_basic(&dict, "Type",
4336                                         DBUS_TYPE_STRING, &type);
4337
4338 #if defined TIZEN_EXT
4339                 SUPPLICANT_DBG("[specific_scan] num_ssids %d", data->scan_params->num_ssids);
4340                 if (data->scan_params->num_ssids != 0)
4341 #endif
4342                         supplicant_dbus_dict_append_array(&dict, "SSIDs",
4343                                                 DBUS_TYPE_STRING,
4344                                                 append_ssids,
4345                                                 data->scan_params);
4346
4347                 supplicant_add_scan_frequency(&dict, add_scan_frequencies,
4348                                                 data->scan_params);
4349         } else
4350                 supplicant_dbus_dict_append_basic(&dict, "Type",
4351                                         DBUS_TYPE_STRING, &type);
4352
4353         supplicant_dbus_dict_close(iter, &dict);
4354 }
4355
4356 static int interface_ready_to_scan(GSupplicantInterface *interface)
4357 {
4358         if (!interface)
4359                 return -EINVAL;
4360
4361         if (!system_available)
4362                 return -EFAULT;
4363
4364         if (interface->scanning)
4365                 return -EALREADY;
4366
4367         switch (interface->state) {
4368         case G_SUPPLICANT_STATE_AUTHENTICATING:
4369         case G_SUPPLICANT_STATE_ASSOCIATING:
4370         case G_SUPPLICANT_STATE_ASSOCIATED:
4371         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4372         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4373                 return -EBUSY;
4374 #if defined TIZEN_EXT
4375         case G_SUPPLICANT_STATE_DISABLED:
4376                 return -ENOLINK;
4377         case G_SUPPLICANT_STATE_UNKNOWN:
4378 #else
4379         case G_SUPPLICANT_STATE_UNKNOWN:
4380         case G_SUPPLICANT_STATE_DISABLED:
4381 #endif
4382         case G_SUPPLICANT_STATE_DISCONNECTED:
4383         case G_SUPPLICANT_STATE_INACTIVE:
4384         case G_SUPPLICANT_STATE_SCANNING:
4385         case G_SUPPLICANT_STATE_COMPLETED:
4386                 break;
4387         }
4388
4389         return 0;
4390 }
4391
4392 int g_supplicant_interface_scan(GSupplicantInterface *interface,
4393                                 GSupplicantScanParams *scan_data,
4394                                 GSupplicantInterfaceCallback callback,
4395                                                         void *user_data)
4396 {
4397         struct interface_scan_data *data;
4398         int ret;
4399
4400         ret = interface_ready_to_scan(interface);
4401         if (ret)
4402                 return ret;
4403
4404         data = dbus_malloc0(sizeof(*data));
4405         if (!data)
4406                 return -ENOMEM;
4407
4408         data->interface = interface;
4409         data->path = g_strdup(interface->path);
4410 #if defined TIZEN_EXT
4411         data->interface->scan_callback = data->callback = callback;
4412         data->interface->scan_data = data->user_data = user_data;
4413 #else
4414         data->callback = callback;
4415         data->user_data = user_data;
4416 #endif
4417         data->scan_params = scan_data;
4418
4419         interface->scan_callback = callback;
4420         interface->scan_data = user_data;
4421
4422         ret = supplicant_dbus_method_call(interface->path,
4423                         SUPPLICANT_INTERFACE ".Interface", "Scan",
4424                         interface_scan_params, interface_scan_result, data,
4425                         interface);
4426
4427         if (ret < 0) {
4428                 g_free(data->path);
4429                 dbus_free(data);
4430         }
4431
4432         return ret;
4433 }
4434
4435 static int parse_supplicant_error(DBusMessageIter *iter)
4436 {
4437         int err = -ECANCELED;
4438         char *key;
4439
4440         if (!iter)
4441                 return err;
4442
4443         /* If the given passphrase is malformed wpa_s returns
4444          * "invalid message format" but this error should be interpreted as
4445          * invalid-key.
4446          */
4447         while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
4448                 dbus_message_iter_get_basic(iter, &key);
4449                 if (strncmp(key, "psk", 3) == 0 ||
4450                                 strncmp(key, "wep_key", 7) == 0 ||
4451                                 strcmp(key, "invalid message format") == 0) {
4452                         err = -ENOKEY;
4453                         break;
4454                 }
4455                 dbus_message_iter_next(iter);
4456         }
4457
4458         return err;
4459 }
4460
4461 static void interface_select_network_result(const char *error,
4462                                 DBusMessageIter *iter, void *user_data)
4463 {
4464         struct interface_connect_data *data = user_data;
4465         int err;
4466
4467         SUPPLICANT_DBG("");
4468
4469         err = 0;
4470         if (error) {
4471 #if defined TIZEN_EXT
4472                 SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
4473 #else
4474                 SUPPLICANT_DBG("SelectNetwork error %s", error);
4475 #endif
4476                 err = parse_supplicant_error(iter);
4477         }
4478
4479         g_free(data->path);
4480
4481         if (data->callback)
4482                 data->callback(err, data->interface, data->user_data);
4483
4484         g_free(data->ssid);
4485         dbus_free(data);
4486 }
4487
4488 static void interface_select_network_params(DBusMessageIter *iter,
4489                                                         void *user_data)
4490 {
4491         struct interface_connect_data *data = user_data;
4492         GSupplicantInterface *interface = data->interface;
4493 #if defined TIZEN_EXT
4494         GSupplicantSSID *ssid = data->ssid;
4495 #endif
4496
4497         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
4498                                         &interface->network_path);
4499 #if defined TIZEN_EXT
4500         dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
4501 #endif
4502 }
4503
4504 static void interface_add_network_result(const char *error,
4505                                 DBusMessageIter *iter, void *user_data)
4506 {
4507         struct interface_connect_data *data = user_data;
4508         GSupplicantInterface *interface = data->interface;
4509         const char *path;
4510         int err;
4511
4512         if (error)
4513                 goto error;
4514
4515         dbus_message_iter_get_basic(iter, &path);
4516         if (!path)
4517                 goto error;
4518
4519         SUPPLICANT_DBG("PATH: %s", path);
4520
4521         g_free(interface->network_path);
4522         interface->network_path = g_strdup(path);
4523
4524 #if defined TIZEN_EXT
4525         SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
4526 #endif
4527
4528 #if defined TIZEN_EXT
4529         supplicant_dbus_method_call(data->interface->path,
4530                         SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
4531                         interface_select_network_params,
4532                         interface_select_network_result, data,
4533                         interface);
4534 #else
4535         supplicant_dbus_method_call(data->interface->path,
4536                         SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
4537                         interface_select_network_params,
4538                         interface_select_network_result, data,
4539                         interface);
4540 #endif
4541
4542         return;
4543
4544 error:
4545         SUPPLICANT_DBG("AddNetwork error %s", error);
4546
4547         if (interface_exists(data->interface, data->interface->path)) {
4548                 err = parse_supplicant_error(iter);
4549                 if (data->callback)
4550                         data->callback(err, data->interface, data->user_data);
4551
4552                 g_free(interface->network_path);
4553                 interface->network_path = NULL;
4554         }
4555
4556         g_free(data->path);
4557         g_free(data->ssid);
4558         g_free(data);
4559 }
4560
4561 static void add_network_security_none(DBusMessageIter *dict)
4562 {
4563         const char *auth_alg = "OPEN";
4564
4565         supplicant_dbus_dict_append_basic(dict, "auth_alg",
4566                                         DBUS_TYPE_STRING, &auth_alg);
4567 }
4568
4569 static void add_network_security_wep(DBusMessageIter *dict,
4570                                         GSupplicantSSID *ssid)
4571 {
4572         const char *auth_alg = "OPEN SHARED";
4573         dbus_uint32_t key_index = 0;
4574
4575         supplicant_dbus_dict_append_basic(dict, "auth_alg",
4576                                         DBUS_TYPE_STRING, &auth_alg);
4577
4578         if (ssid->passphrase) {
4579                 int size = strlen(ssid->passphrase);
4580                 if (size == 10 || size == 26) {
4581                         unsigned char *key = g_try_malloc(13);
4582                         char tmp[3];
4583                         int i;
4584
4585                         memset(tmp, 0, sizeof(tmp));
4586                         if (!key)
4587                                 size = 0;
4588
4589                         for (i = 0; i < size / 2; i++) {
4590                                 memcpy(tmp, ssid->passphrase + (i * 2), 2);
4591                                 key[i] = (unsigned char) strtol(tmp, NULL, 16);
4592                         }
4593
4594                         supplicant_dbus_dict_append_fixed_array(dict,
4595                                                         "wep_key0",
4596                                                         DBUS_TYPE_BYTE,
4597                                                         &key, size / 2);
4598                         g_free(key);
4599                 } else if (size == 5 || size == 13) {
4600                         unsigned char *key = g_try_malloc(13);
4601                         int i;
4602
4603                         if (!key)
4604                                 size = 0;
4605
4606                         for (i = 0; i < size; i++)
4607                                 key[i] = (unsigned char) ssid->passphrase[i];
4608
4609                         supplicant_dbus_dict_append_fixed_array(dict,
4610                                                                 "wep_key0",
4611                                                                 DBUS_TYPE_BYTE,
4612                                                                 &key, size);
4613                         g_free(key);
4614                 } else
4615                         supplicant_dbus_dict_append_basic(dict,
4616                                                         "wep_key0",
4617                                                         DBUS_TYPE_STRING,
4618                                                         &ssid->passphrase);
4619
4620                 supplicant_dbus_dict_append_basic(dict, "wep_tx_keyidx",
4621                                         DBUS_TYPE_UINT32, &key_index);
4622         }
4623 }
4624
4625 static dbus_bool_t is_psk_raw_key(const char *psk)
4626 {
4627         int i;
4628
4629         /* A raw key is always 64 bytes length... */
4630         if (strlen(psk) != 64)
4631                 return FALSE;
4632
4633         /* ... and its content is in hex representation */
4634         for (i = 0; i < 64; i++)
4635                 if (!isxdigit((unsigned char) psk[i]))
4636                         return FALSE;
4637
4638         return TRUE;
4639 }
4640
4641 static unsigned char hexchar2bin(char c)
4642 {
4643         if ((c >= '0') && (c <= '9'))
4644                 return c - '0';
4645         else if ((c >= 'A') && (c <= 'F'))
4646                 return c - 'A' + 10;
4647         else if ((c >= 'a') && (c <= 'f'))
4648                 return c - 'a' + 10;
4649         else
4650                 return c;
4651 }
4652
4653 static void hexstring2bin(const char *string, unsigned char *data,
4654                                 size_t data_len)
4655 {
4656         size_t i;
4657
4658         for (i = 0; i < data_len; i++)
4659                 data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
4660                            hexchar2bin(string[i * 2 + 1]) << 0);
4661 }
4662
4663 static void add_network_security_psk(DBusMessageIter *dict,
4664                                         GSupplicantSSID *ssid)
4665 {
4666         if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
4667                 const char *key = "psk";
4668
4669                 if (is_psk_raw_key(ssid->passphrase)) {
4670                         unsigned char data[32];
4671                         unsigned char *datap = data;
4672
4673                         /* The above pointer alias is required by D-Bus because
4674                          * with D-Bus and GCC, non-heap-allocated arrays cannot
4675                          * be passed directly by their base pointer. */
4676
4677                         hexstring2bin(ssid->passphrase, datap, sizeof(data));
4678
4679                         supplicant_dbus_dict_append_fixed_array(dict,
4680                                                         key, DBUS_TYPE_BYTE,
4681                                                         &datap, sizeof(data));
4682                 } else
4683                         supplicant_dbus_dict_append_basic(dict,
4684                                                         key, DBUS_TYPE_STRING,
4685                                                         &ssid->passphrase);
4686         }
4687 }
4688
4689 static void add_network_security_tls(DBusMessageIter *dict,
4690                                         GSupplicantSSID *ssid)
4691 {
4692         /*
4693          * For TLS, we at least need:
4694          *              The client certificate
4695          *              The client private key file
4696          *              The client private key file password
4697          *
4698          * The Authority certificate is optional.
4699          */
4700         if (!ssid->client_cert_path)
4701                 return;
4702
4703         if (!ssid->private_key_path)
4704                 return;
4705
4706 #if !defined TIZEN_EXT
4707         if (!ssid->private_key_passphrase)
4708                 return;
4709 #endif
4710
4711         if (ssid->ca_cert_path)
4712                 supplicant_dbus_dict_append_basic(dict, "ca_cert",
4713                                         DBUS_TYPE_STRING, &ssid->ca_cert_path);
4714
4715         supplicant_dbus_dict_append_basic(dict, "private_key",
4716                                                 DBUS_TYPE_STRING,
4717                                                 &ssid->private_key_path);
4718 #if !defined TIZEN_EXT
4719         supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
4720                                                 DBUS_TYPE_STRING,
4721                                                 &ssid->private_key_passphrase);
4722 #endif
4723         supplicant_dbus_dict_append_basic(dict, "client_cert",
4724                                                 DBUS_TYPE_STRING,
4725                                                 &ssid->client_cert_path);
4726 }
4727
4728 static void add_network_security_peap(DBusMessageIter *dict,
4729                                         GSupplicantSSID *ssid)
4730 {
4731         char *phase2_auth;
4732
4733         /*
4734          * For PEAP/TTLS, we at least need
4735          *              The authority certificate
4736          *              The 2nd phase authentication method
4737          *              The 2nd phase passphrase
4738          *
4739          * The Client certificate is optional although strongly recommended
4740          * When setting it, we need in addition
4741          *              The Client private key file
4742          *              The Client private key file password
4743          */
4744         if (!ssid->passphrase)
4745                 return;
4746
4747         if (!ssid->phase2_auth)
4748                 return;
4749
4750         if (ssid->client_cert_path) {
4751                 if (!ssid->private_key_path)
4752                         return;
4753
4754 #if !defined TIZEN_EXT
4755                 if (!ssid->private_key_passphrase)
4756                         return;
4757 #endif
4758
4759                 supplicant_dbus_dict_append_basic(dict, "client_cert",
4760                                                 DBUS_TYPE_STRING,
4761                                                 &ssid->client_cert_path);
4762
4763                 supplicant_dbus_dict_append_basic(dict, "private_key",
4764                                                 DBUS_TYPE_STRING,
4765                                                 &ssid->private_key_path);
4766
4767 #if !defined TIZEN_EXT
4768                 supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
4769                                                 DBUS_TYPE_STRING,
4770                                                 &ssid->private_key_passphrase);
4771 #endif
4772
4773         }
4774
4775         if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
4776                 phase2_auth = g_strdup_printf("autheap=%s",
4777                                         ssid->phase2_auth + strlen("EAP-"));
4778         } else
4779                 phase2_auth = g_strdup_printf("auth=%s", ssid->phase2_auth);
4780
4781         supplicant_dbus_dict_append_basic(dict, "password",
4782                                                 DBUS_TYPE_STRING,
4783                                                 &ssid->passphrase);
4784
4785         if (ssid->ca_cert_path)
4786                 supplicant_dbus_dict_append_basic(dict, "ca_cert",
4787                                                 DBUS_TYPE_STRING,
4788                                                 &ssid->ca_cert_path);
4789
4790         supplicant_dbus_dict_append_basic(dict, "phase2",
4791                                                 DBUS_TYPE_STRING,
4792                                                 &phase2_auth);
4793
4794         g_free(phase2_auth);
4795 }
4796
4797 #if defined TIZEN_EXT
4798 static void add_network_security_aka_sim(DBusMessageIter *dict,
4799                                         GSupplicantSSID *ssid)
4800 {
4801         if (!ssid->passphrase)
4802                 return;
4803
4804         supplicant_dbus_dict_append_basic(dict, "password",
4805                         DBUS_TYPE_STRING,
4806                         &ssid->passphrase);
4807 }
4808 #endif
4809
4810 static void add_network_security_eap(DBusMessageIter *dict,
4811                                         GSupplicantSSID *ssid)
4812 {
4813         char *eap_value;
4814
4815 #if defined TIZEN_EXT
4816         if (!ssid->eap)
4817 #else
4818         if (!ssid->eap || !ssid->identity)
4819 #endif
4820                 return;
4821
4822         if (g_strcmp0(ssid->eap, "tls") == 0) {
4823                 add_network_security_tls(dict, ssid);
4824         } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
4825                                 g_strcmp0(ssid->eap, "ttls") == 0) {
4826 #if defined TIZEN_EXT
4827                 if (!ssid->identity)
4828                         return;
4829 #endif
4830                 add_network_security_peap(dict, ssid);
4831
4832 #if defined TIZEN_EXT
4833         } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
4834                         g_strcmp0(ssid->eap, "aka") == 0) {
4835                 add_network_security_aka_sim(dict, ssid);
4836 #endif
4837         } else
4838                 return;
4839
4840         eap_value = g_ascii_strup(ssid->eap, -1);
4841
4842         supplicant_dbus_dict_append_basic(dict, "eap",
4843                                                 DBUS_TYPE_STRING,
4844                                                 &eap_value);
4845 #if defined TIZEN_EXT
4846         if (ssid->identity != NULL)
4847                 supplicant_dbus_dict_append_basic(dict, "identity",
4848                                                         DBUS_TYPE_STRING,
4849                                                         &ssid->identity);
4850 #else
4851         supplicant_dbus_dict_append_basic(dict, "identity",
4852                                                 DBUS_TYPE_STRING,
4853                                                 &ssid->identity);
4854 #endif
4855
4856         g_free(eap_value);
4857 }
4858
4859 static void add_network_security_ciphers(DBusMessageIter *dict,
4860                                                 GSupplicantSSID *ssid)
4861 {
4862         unsigned int p_cipher, g_cipher, i;
4863         char *pairwise, *group;
4864         char *pair_ciphers[4];
4865         char *group_ciphers[5];
4866
4867         p_cipher = ssid->pairwise_cipher;
4868         g_cipher = ssid->group_cipher;
4869
4870         if (p_cipher == 0 && g_cipher == 0)
4871                 return;
4872
4873         i = 0;
4874
4875         if (p_cipher & G_SUPPLICANT_PAIRWISE_CCMP)
4876                 pair_ciphers[i++] = "CCMP";
4877
4878         if (p_cipher & G_SUPPLICANT_PAIRWISE_TKIP)
4879                 pair_ciphers[i++] = "TKIP";
4880
4881         if (p_cipher & G_SUPPLICANT_PAIRWISE_NONE)
4882                 pair_ciphers[i++] = "NONE";
4883
4884         pair_ciphers[i] = NULL;
4885
4886         i = 0;
4887
4888         if (g_cipher & G_SUPPLICANT_GROUP_CCMP)
4889                 group_ciphers[i++] = "CCMP";
4890
4891         if (g_cipher & G_SUPPLICANT_GROUP_TKIP)
4892                 group_ciphers[i++] = "TKIP";
4893
4894         if (g_cipher & G_SUPPLICANT_GROUP_WEP104)
4895                 group_ciphers[i++] = "WEP104";
4896
4897         if (g_cipher & G_SUPPLICANT_GROUP_WEP40)
4898                 group_ciphers[i++] = "WEP40";
4899
4900         group_ciphers[i] = NULL;
4901
4902         pairwise = g_strjoinv(" ", pair_ciphers);
4903         group = g_strjoinv(" ", group_ciphers);
4904
4905         SUPPLICANT_DBG("cipher %s %s", pairwise, group);
4906
4907         supplicant_dbus_dict_append_basic(dict, "pairwise",
4908                                                 DBUS_TYPE_STRING,
4909                                                 &pairwise);
4910         supplicant_dbus_dict_append_basic(dict, "group",
4911                                                 DBUS_TYPE_STRING,
4912                                                 &group);
4913
4914         g_free(pairwise);
4915         g_free(group);
4916 }
4917
4918 static void add_network_security_proto(DBusMessageIter *dict,
4919                                                 GSupplicantSSID *ssid)
4920 {
4921         unsigned int protocol, i;
4922         char *proto;
4923         char *protos[3];
4924
4925         protocol = ssid->protocol;
4926
4927         if (protocol == 0)
4928                 return;
4929
4930         i = 0;
4931
4932         if (protocol & G_SUPPLICANT_PROTO_RSN)
4933                 protos[i++] = "RSN";
4934
4935         if (protocol & G_SUPPLICANT_PROTO_WPA)
4936                 protos[i++] = "WPA";
4937
4938         protos[i] = NULL;
4939
4940         proto = g_strjoinv(" ", protos);
4941
4942         SUPPLICANT_DBG("proto %s", proto);
4943
4944         supplicant_dbus_dict_append_basic(dict, "proto",
4945                                                 DBUS_TYPE_STRING,
4946                                                 &proto);
4947
4948         g_free(proto);
4949 }
4950
4951 static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
4952 {
4953         char *key_mgmt;
4954
4955         switch (ssid->security) {
4956         case G_SUPPLICANT_SECURITY_NONE:
4957                 key_mgmt = "NONE";
4958                 add_network_security_none(dict);
4959                 add_network_security_ciphers(dict, ssid);
4960                 break;
4961         case G_SUPPLICANT_SECURITY_UNKNOWN:
4962         case G_SUPPLICANT_SECURITY_WEP:
4963                 key_mgmt = "NONE";
4964                 add_network_security_wep(dict, ssid);
4965                 add_network_security_ciphers(dict, ssid);
4966                 break;
4967         case G_SUPPLICANT_SECURITY_PSK:
4968                 key_mgmt = "WPA-PSK";
4969                 add_network_security_psk(dict, ssid);
4970                 add_network_security_ciphers(dict, ssid);
4971                 add_network_security_proto(dict, ssid);
4972                 break;
4973         case G_SUPPLICANT_SECURITY_IEEE8021X:
4974                 key_mgmt = "WPA-EAP";
4975                 add_network_security_eap(dict, ssid);
4976                 add_network_security_ciphers(dict, ssid);
4977                 add_network_security_proto(dict, ssid);
4978                 break;
4979 #if defined TIZEN_EXT
4980         case G_SUPPLICANT_SECURITY_FT_PSK:
4981                 key_mgmt = "FT-PSK";
4982                 add_network_security_psk(dict, ssid);
4983                 add_network_security_ciphers(dict, ssid);
4984                 add_network_security_proto(dict, ssid);
4985                 break;
4986         case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
4987                 key_mgmt = "FT-EAP";
4988                 add_network_security_eap(dict, ssid);
4989                 add_network_security_ciphers(dict, ssid);
4990                 add_network_security_proto(dict, ssid);
4991                 break;
4992 #endif
4993         }
4994
4995         supplicant_dbus_dict_append_basic(dict, "key_mgmt",
4996                                 DBUS_TYPE_STRING, &key_mgmt);
4997 }
4998
4999 static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
5000 {
5001         dbus_uint32_t mode;
5002
5003         switch (ssid->mode) {
5004         case G_SUPPLICANT_MODE_UNKNOWN:
5005         case G_SUPPLICANT_MODE_INFRA:
5006                 mode = 0;
5007                 break;
5008         case G_SUPPLICANT_MODE_IBSS:
5009                 mode = 1;
5010                 break;
5011         case G_SUPPLICANT_MODE_MASTER:
5012                 mode = 2;
5013                 break;
5014         }
5015
5016         supplicant_dbus_dict_append_basic(dict, "mode",
5017                                 DBUS_TYPE_UINT32, &mode);
5018 }
5019
5020 static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
5021 {
5022         DBusMessageIter dict;
5023         struct interface_connect_data *data = user_data;
5024         GSupplicantSSID *ssid = data->ssid;
5025
5026         supplicant_dbus_dict_open(iter, &dict);
5027
5028         if (ssid->scan_ssid)
5029                 supplicant_dbus_dict_append_basic(&dict, "scan_ssid",
5030                                          DBUS_TYPE_UINT32, &ssid->scan_ssid);
5031
5032         if (ssid->freq)
5033                 supplicant_dbus_dict_append_basic(&dict, "frequency",
5034                                          DBUS_TYPE_UINT32, &ssid->freq);
5035
5036         if (ssid->bgscan)
5037                 supplicant_dbus_dict_append_basic(&dict, "bgscan",
5038                                         DBUS_TYPE_STRING, &ssid->bgscan);
5039
5040         add_network_mode(&dict, ssid);
5041
5042         add_network_security(&dict, ssid);
5043
5044         supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
5045                                         DBUS_TYPE_BYTE, &ssid->ssid,
5046                                                 ssid->ssid_len);
5047
5048         supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid",
5049                                         DBUS_TYPE_INT32,
5050                                         &ssid->ignore_broadcast_ssid);
5051
5052 #if defined TIZEN_EXT
5053         if (ssid->bssid) {
5054                 char *bssid = NULL;
5055                 bssid = g_try_malloc0(18);
5056                 if (bssid == NULL) {
5057                         SUPPLICANT_DBG("memory allocation error");
5058                         supplicant_dbus_dict_close(iter, &dict);
5059                         return;
5060                 }
5061                 snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
5062                                         ssid->bssid[0], ssid->bssid[1], ssid->bssid[2],
5063                                         ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]);
5064                 supplicant_dbus_dict_append_basic(&dict, "bssid",
5065                                         DBUS_TYPE_STRING, &bssid);
5066                 g_free(bssid);
5067         }
5068 #endif
5069
5070         supplicant_dbus_dict_close(iter, &dict);
5071 }
5072
5073 static void interface_wps_start_result(const char *error,
5074                                 DBusMessageIter *iter, void *user_data)
5075 {
5076         struct interface_connect_data *data = user_data;
5077         int err;
5078
5079         SUPPLICANT_DBG("");
5080
5081         err = 0;
5082         if (error) {
5083                 SUPPLICANT_DBG("error: %s", error);
5084                 err = parse_supplicant_error(iter);
5085         }
5086
5087         if(data->callback)
5088                 data->callback(err, data->interface, data->user_data);
5089
5090         g_free(data->path);
5091         g_free(data->ssid);
5092         dbus_free(data);
5093 }
5094
5095 static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
5096 {
5097         struct interface_connect_data *data = user_data;
5098         GSupplicantSSID *ssid = data->ssid;
5099         const char *role = "enrollee", *type;
5100         DBusMessageIter dict;
5101
5102         SUPPLICANT_DBG("");
5103
5104         supplicant_dbus_dict_open(iter, &dict);
5105
5106         supplicant_dbus_dict_append_basic(&dict, "Role",
5107                                                 DBUS_TYPE_STRING, &role);
5108
5109         type = "pbc";
5110         if (ssid->pin_wps) {
5111                 type = "pin";
5112                 supplicant_dbus_dict_append_basic(&dict, "Pin",
5113                                         DBUS_TYPE_STRING, &ssid->pin_wps);
5114         }
5115
5116         supplicant_dbus_dict_append_basic(&dict, "Type",
5117                                         DBUS_TYPE_STRING, &type);
5118
5119 #if defined TIZEN_EXT
5120         if (ssid->bssid)
5121                 supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
5122                                                 DBUS_TYPE_BYTE, &ssid->bssid, 6);
5123 #endif
5124
5125         supplicant_dbus_dict_close(iter, &dict);
5126 }
5127
5128 static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
5129 {
5130         struct interface_connect_data *data = user_data;
5131
5132         SUPPLICANT_DBG("");
5133
5134         if (error) {
5135                 SUPPLICANT_DBG("error: %s", error);
5136                 g_free(data->path);
5137                 g_free(data->ssid);
5138                 dbus_free(data);
5139                 return;
5140         }
5141 #if defined TIZEN_EXT
5142         GSupplicantSSID *ssid = data->ssid;
5143         if (ssid->pin_wps != NULL) {
5144                 if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
5145                         SUPPLICANT_DBG("Invalid characters in WPS_PIN");
5146                         g_free(data->ssid);
5147                         dbus_free(data);
5148                         return;
5149                 }
5150         }
5151 #endif
5152         supplicant_dbus_method_call(data->interface->path,
5153                         SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
5154                         interface_add_wps_params,
5155                         interface_wps_start_result, data, NULL);
5156 }
5157
5158 static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
5159 {
5160         dbus_bool_t credentials = TRUE;
5161
5162         SUPPLICANT_DBG("");
5163
5164         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
5165 }
5166
5167
5168 int g_supplicant_interface_connect(GSupplicantInterface *interface,
5169                                 GSupplicantSSID *ssid,
5170                                 GSupplicantInterfaceCallback callback,
5171                                                         void *user_data)
5172 {
5173         struct interface_connect_data *data;
5174         int ret;
5175
5176         if (!interface)
5177                 return -EINVAL;
5178
5179         if (!system_available)
5180                 return -EFAULT;
5181
5182         /* TODO: Check if we're already connected and switch */
5183
5184         data = dbus_malloc0(sizeof(*data));
5185         if (!data)
5186                 return -ENOMEM;
5187
5188         data->interface = interface;
5189         data->path = g_strdup(interface->path);
5190         data->callback = callback;
5191         data->ssid = ssid;
5192         data->user_data = user_data;
5193
5194         if (ssid->use_wps) {
5195                 g_free(interface->wps_cred.key);
5196                 memset(&interface->wps_cred, 0,
5197                                 sizeof(struct _GSupplicantWpsCredentials));
5198
5199                 ret = supplicant_dbus_property_set(interface->path,
5200                         SUPPLICANT_INTERFACE ".Interface.WPS",
5201                         "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
5202                         wps_process_credentials, wps_start, data, interface);
5203         } else
5204                 ret = supplicant_dbus_method_call(interface->path,
5205                         SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
5206                         interface_add_network_params,
5207                         interface_add_network_result, data,
5208                         interface);
5209
5210         if (ret < 0) {
5211                 g_free(data->path);
5212                 dbus_free(data);
5213                 return ret;
5214         }
5215
5216         return -EINPROGRESS;
5217 }
5218
5219 static void network_remove_result(const char *error,
5220                                 DBusMessageIter *iter, void *user_data)
5221 {
5222         struct interface_data *data = user_data;
5223         int result = 0;
5224
5225         SUPPLICANT_DBG("");
5226
5227         if (error) {
5228                 result = -EIO;
5229                 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
5230                                                 error) == 0)
5231                         result = -ECONNABORTED;
5232         }
5233
5234         g_free(data->path);
5235
5236         if (data->callback)
5237                 data->callback(result, data->interface, data->user_data);
5238
5239         dbus_free(data);
5240 }
5241
5242 static void network_remove_params(DBusMessageIter *iter, void *user_data)
5243 {
5244         struct interface_data *data = user_data;
5245         const char *path = data->interface->network_path;
5246
5247         SUPPLICANT_DBG("path %s", path);
5248
5249         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
5250 }
5251
5252 static int network_remove(struct interface_data *data)
5253 {
5254         GSupplicantInterface *interface = data->interface;
5255
5256         SUPPLICANT_DBG("");
5257
5258 #if defined TIZEN_EXT
5259         GSupplicantInterface *intf = NULL;
5260         /*
5261          * Check if 'interface' is valid
5262          */
5263         intf = g_hash_table_lookup(interface_table, interface->path);
5264         if (intf == NULL)
5265                 return -EINVAL;
5266 #endif
5267
5268         return supplicant_dbus_method_call(interface->path,
5269                         SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
5270                         network_remove_params, network_remove_result, data,
5271                         interface);
5272 }
5273
5274 static void interface_disconnect_result(const char *error,
5275                                 DBusMessageIter *iter, void *user_data)
5276 {
5277         struct interface_data *data = user_data;
5278         int result = 0;
5279
5280         SUPPLICANT_DBG("");
5281
5282         if (error) {
5283                 result = -EIO;
5284                 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
5285                                                 error) == 0)
5286                         result = -ECONNABORTED;
5287         }
5288
5289         if (result < 0 && data->callback) {
5290                 data->callback(result, data->interface, data->user_data);
5291                 data->callback = NULL;
5292         }
5293
5294         /* If we are disconnecting from previous WPS successful
5295          * association. i.e.: it did not went through AddNetwork,
5296          * and interface->network_path was never set. */
5297         if (!data->interface->network_path) {
5298                 g_free(data->path);
5299                 dbus_free(data);
5300                 return;
5301         }
5302
5303         if (result != -ECONNABORTED) {
5304                 if (network_remove(data) < 0) {
5305                         g_free(data->path);
5306                         dbus_free(data);
5307                 }
5308         } else {
5309                 g_free(data->path);
5310                 dbus_free(data);
5311         }
5312 }
5313
5314 int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
5315                                         GSupplicantInterfaceCallback callback,
5316                                                         void *user_data)
5317 {
5318         struct interface_data *data;
5319         int ret;
5320
5321         SUPPLICANT_DBG("");
5322
5323         if (!interface)
5324                 return -EINVAL;
5325
5326         if (!system_available)
5327                 return -EFAULT;
5328
5329         data = dbus_malloc0(sizeof(*data));
5330         if (!data)
5331                 return -ENOMEM;
5332
5333         data->interface = interface;
5334         data->path = g_strdup(interface->path);
5335         data->callback = callback;
5336         data->user_data = user_data;
5337
5338         ret = supplicant_dbus_method_call(interface->path,
5339                         SUPPLICANT_INTERFACE ".Interface", "Disconnect",
5340                         NULL, interface_disconnect_result, data,
5341                         interface);
5342
5343         if (ret < 0) {
5344                 g_free(data->path);
5345                 dbus_free(data);
5346         }
5347
5348         return ret;
5349 }
5350
5351 static void interface_p2p_find_result(const char *error,
5352                                         DBusMessageIter *iter, void *user_data)
5353 {
5354         struct interface_scan_data *data = user_data;
5355         int err = 0;
5356
5357         SUPPLICANT_DBG("error %s", error);
5358
5359         if (error)
5360                 err = -EIO;
5361
5362         if (interface_exists(data->interface, data->path)) {
5363                 if (!data->interface->ready)
5364                         err = -ENOLINK;
5365                 if (!err)
5366                         data->interface->p2p_finding = true;
5367         }
5368
5369         if (data->callback)
5370                 data->callback(err, data->interface, data->user_data);
5371
5372         g_free(data->path);
5373         dbus_free(data);
5374 }
5375
5376 static void interface_p2p_find_params(DBusMessageIter *iter, void *user_data)
5377 {
5378         DBusMessageIter dict;
5379
5380         supplicant_dbus_dict_open(iter, &dict);
5381         supplicant_dbus_dict_close(iter, &dict);
5382 }
5383
5384 int g_supplicant_interface_p2p_find(GSupplicantInterface *interface,
5385                                         GSupplicantInterfaceCallback callback,
5386                                                         void *user_data)
5387 {
5388         struct interface_scan_data *data;
5389         int ret;
5390
5391         if (!interface->p2p_support)
5392                 return -ENOTSUP;
5393
5394         ret = interface_ready_to_scan(interface);
5395         if (ret && ret != -EALREADY)
5396                 return ret;
5397
5398         data = dbus_malloc0(sizeof(*data));
5399         if (!data)
5400                 return -ENOMEM;
5401
5402         data->interface = interface;
5403         data->path = g_strdup(interface->path);
5404         data->callback = callback;
5405         data->user_data = user_data;
5406
5407         ret = supplicant_dbus_method_call(interface->path,
5408                         SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Find",
5409                         interface_p2p_find_params, interface_p2p_find_result,
5410                         data, interface);
5411         if (ret < 0) {
5412                 g_free(data->path);
5413                 dbus_free(data);
5414         }
5415
5416         return ret;
5417 }
5418
5419 bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface)
5420 {
5421         if (!interface)
5422                 return false;
5423
5424         return interface->p2p_finding;
5425 }
5426
5427 int g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface)
5428 {
5429         if (!interface->p2p_finding)
5430                 return 0;
5431
5432         SUPPLICANT_DBG("");
5433
5434         interface->p2p_finding = false;
5435
5436         return supplicant_dbus_method_call(interface->path,
5437                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "StopFind",
5438                 NULL, NULL, NULL, NULL);
5439 }
5440
5441 static void interface_p2p_connect_result(const char *error,
5442                                         DBusMessageIter *iter, void *user_data)
5443 {
5444         struct interface_connect_data *data = user_data;
5445         int err = 0;
5446
5447         SUPPLICANT_DBG("");
5448
5449         if (error)
5450                 err = parse_supplicant_error(iter);
5451
5452         if (data->callback)
5453                 data->callback(err, data->interface, data->user_data);
5454
5455         g_free(data->path);
5456         g_free(data->peer->wps_pin);
5457         g_free(data->peer->path);
5458         g_free(data->peer);
5459         g_free(data);
5460 }
5461
5462 static void interface_p2p_connect_params(DBusMessageIter *iter, void *user_data)
5463 {
5464         struct interface_connect_data *data = user_data;
5465         const char *wps = "pbc";
5466         DBusMessageIter dict;
5467         int go_intent = 7;
5468
5469         SUPPLICANT_DBG("");
5470
5471         supplicant_dbus_dict_open(iter, &dict);
5472
5473         if (data->peer->master)
5474                 go_intent = 15;
5475
5476         if (data->peer->wps_pin)
5477                 wps = "pin";
5478
5479         supplicant_dbus_dict_append_basic(&dict, "peer",
5480                                 DBUS_TYPE_OBJECT_PATH, &data->peer->path);
5481         supplicant_dbus_dict_append_basic(&dict, "wps_method",
5482                                 DBUS_TYPE_STRING, &wps);
5483         if (data->peer->wps_pin) {
5484                 supplicant_dbus_dict_append_basic(&dict, "pin",
5485                                 DBUS_TYPE_STRING, &data->peer->wps_pin);
5486         }
5487
5488         supplicant_dbus_dict_append_basic(&dict, "go_intent",
5489                                         DBUS_TYPE_INT32, &go_intent);
5490
5491         supplicant_dbus_dict_close(iter, &dict);
5492 }
5493
5494 int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
5495                                         GSupplicantPeerParams *peer_params,
5496                                         GSupplicantInterfaceCallback callback,
5497                                         void *user_data)
5498 {
5499         struct interface_connect_data *data;
5500         int ret;
5501
5502         SUPPLICANT_DBG("");
5503
5504         if (!interface->p2p_support)
5505                 return -ENOTSUP;
5506
5507         data = dbus_malloc0(sizeof(*data));
5508         data->interface = interface;
5509         data->path = g_strdup(interface->path);
5510         data->peer = peer_params;
5511         data->callback = callback;
5512         data->user_data = user_data;
5513
5514         ret = supplicant_dbus_method_call(interface->path,
5515                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Connect",
5516                 interface_p2p_connect_params, interface_p2p_connect_result,
5517                 data, interface);
5518         if (ret < 0) {
5519                 g_free(data->path);
5520                 dbus_free(data);
5521                 return ret;
5522         }
5523
5524         return -EINPROGRESS;
5525 }
5526
5527 int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
5528                                         GSupplicantPeerParams *peer_params)
5529 {
5530         GSupplicantPeer *peer;
5531         int count = 0;
5532         GSList *list;
5533
5534         SUPPLICANT_DBG("");
5535
5536         if (!interface->p2p_support)
5537                 return -ENOTSUP;
5538
5539         peer = g_hash_table_lookup(interface->peer_table, peer_params->path);
5540         if (!peer)
5541                 return -ENODEV;
5542
5543         for (list = peer->groups; list; list = list->next, count++) {
5544                 const char *group_obj_path = list->data;
5545                 GSupplicantInterface *g_interface;
5546                 GSupplicantGroup *group;
5547
5548                 group = g_hash_table_lookup(group_mapping, group_obj_path);
5549                 if (!group || !group->interface)
5550                         continue;
5551
5552                 g_interface = group->interface;
5553                 supplicant_dbus_method_call(g_interface->path,
5554                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
5555                                 "Disconnect", NULL, NULL, NULL, g_interface);
5556         }
5557
5558         if (count == 0 && peer->current_group_iface) {
5559                 supplicant_dbus_method_call(peer->current_group_iface->path,
5560                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
5561                                 "Disconnect", NULL, NULL, NULL,
5562                                 peer->current_group_iface->path);
5563         }
5564
5565         peer->current_group_iface = NULL;
5566
5567         return -EINPROGRESS;
5568 }
5569
5570 struct p2p_service_data {
5571         bool registration;
5572         GSupplicantInterface *interface;
5573         GSupplicantP2PServiceParams *service;
5574         GSupplicantInterfaceCallback callback;
5575         void *user_data;
5576 };
5577
5578 static void interface_p2p_service_result(const char *error,
5579                                         DBusMessageIter *iter, void *user_data)
5580 {
5581         struct p2p_service_data *data = user_data;
5582         int result = 0;
5583
5584         SUPPLICANT_DBG("%s result - %s", data->registration ?
5585                                 "Registration" : "Deletion",
5586                                 error ? error : "Success");
5587         if (error)
5588                 result = -EINVAL;
5589
5590         if (data->callback)
5591                 data->callback(result, data->interface, data->user_data);
5592
5593         g_free(data->service->query);
5594         g_free(data->service->response);
5595         g_free(data->service->service);
5596         g_free(data->service->wfd_ies);
5597         g_free(data->service);
5598         dbus_free(data);
5599 }
5600
5601 static void interface_p2p_service_params(DBusMessageIter *iter,
5602                                                         void *user_data)
5603 {
5604         struct p2p_service_data *data = user_data;
5605         GSupplicantP2PServiceParams *service;
5606         DBusMessageIter dict;
5607         const char *type;
5608
5609         SUPPLICANT_DBG("");
5610
5611         service = data->service;
5612
5613         supplicant_dbus_dict_open(iter, &dict);
5614
5615         if (service->query && service->response) {
5616                 type = "bonjour";
5617                 supplicant_dbus_dict_append_basic(&dict, "service_type",
5618                                                 DBUS_TYPE_STRING, &type);
5619                 supplicant_dbus_dict_append_fixed_array(&dict, "query",
5620                                         DBUS_TYPE_BYTE, &service->query,
5621                                         service->query_length);
5622                 supplicant_dbus_dict_append_fixed_array(&dict, "response",
5623                                         DBUS_TYPE_BYTE, &service->response,
5624                                         service->response_length);
5625         } else if (service->version && service->service) {
5626                 type = "upnp";
5627                 supplicant_dbus_dict_append_basic(&dict, "service_type",
5628                                                 DBUS_TYPE_STRING, &type);
5629                 supplicant_dbus_dict_append_basic(&dict, "version",
5630                                         DBUS_TYPE_INT32, &service->version);
5631                 supplicant_dbus_dict_append_basic(&dict, "service",
5632                                         DBUS_TYPE_STRING, &service->service);
5633         }
5634
5635         supplicant_dbus_dict_close(iter, &dict);
5636 }
5637
5638 int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface,
5639                                 GSupplicantInterfaceCallback callback,
5640                                 GSupplicantP2PServiceParams *p2p_service_params,
5641                                 void *user_data)
5642 {
5643         struct p2p_service_data *data;
5644         int ret;
5645
5646         SUPPLICANT_DBG("");
5647
5648         if (!interface->p2p_support)
5649                 return -ENOTSUP;
5650
5651         data = dbus_malloc0(sizeof(*data));
5652         data->registration = true;
5653         data->interface = interface;
5654         data->service = p2p_service_params;
5655         data->callback = callback;
5656         data->user_data = user_data;
5657
5658         ret = supplicant_dbus_method_call(interface->path,
5659                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "AddService",
5660                 interface_p2p_service_params, interface_p2p_service_result,
5661                 data, interface);
5662         if (ret < 0) {
5663                 dbus_free(data);
5664                 return ret;
5665         }
5666
5667         return -EINPROGRESS;
5668 }
5669
5670 int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
5671                                 GSupplicantP2PServiceParams *p2p_service_params)
5672 {
5673         struct p2p_service_data *data;
5674         int ret;
5675
5676         SUPPLICANT_DBG("");
5677
5678         if (!interface->p2p_support)
5679                 return -ENOTSUP;
5680
5681         data = dbus_malloc0(sizeof(*data));
5682         data->interface = interface;
5683         data->service = p2p_service_params;
5684
5685         ret = supplicant_dbus_method_call(interface->path,
5686                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeleteService",
5687                 interface_p2p_service_params, interface_p2p_service_result,
5688                 data, interface);
5689         if (ret < 0) {
5690                 dbus_free(data);
5691                 return ret;
5692         }
5693
5694         return -EINPROGRESS;
5695 }
5696
5697 struct p2p_listen_data {
5698         int period;
5699         int interval;
5700 };
5701
5702 static void interface_p2p_listen_params(DBusMessageIter *iter, void *user_data)
5703 {
5704         struct p2p_listen_data *params = user_data;
5705         DBusMessageIter dict;
5706
5707         supplicant_dbus_dict_open(iter, &dict);
5708
5709         supplicant_dbus_dict_append_basic(&dict, "period",
5710                                         DBUS_TYPE_INT32, &params->period);
5711         supplicant_dbus_dict_append_basic(&dict, "interval",
5712                                         DBUS_TYPE_INT32, &params->interval);
5713         supplicant_dbus_dict_close(iter, &dict);
5714 }
5715
5716 int g_supplicant_interface_p2p_listen(GSupplicantInterface *interface,
5717                                                 int period, int interval)
5718 {
5719         struct p2p_listen_data params;
5720
5721         SUPPLICANT_DBG("");
5722
5723         if (!interface->p2p_support)
5724                 return -ENOTSUP;
5725
5726         params.period = period;
5727         params.interval = interval;
5728
5729         return supplicant_dbus_method_call(interface->path,
5730                         SUPPLICANT_INTERFACE ".Interface.P2PDevice",
5731                         "ExtendedListen", interface_p2p_listen_params,
5732                         NULL, &params, NULL);
5733 }
5734
5735 static void widi_ies_params(DBusMessageIter *iter, void *user_data)
5736 {
5737         struct p2p_service_data *data = user_data;
5738         GSupplicantP2PServiceParams *service = data->service;
5739         DBusMessageIter array;
5740
5741         SUPPLICANT_DBG("%p - %d", service->wfd_ies, service->wfd_ies_length);
5742
5743         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
5744                                         DBUS_TYPE_BYTE_AS_STRING, &array);
5745
5746         if (service->wfd_ies && service->wfd_ies_length > 0) {
5747                 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
5748                                 &service->wfd_ies, service->wfd_ies_length);
5749         }
5750
5751         dbus_message_iter_close_container(iter, &array);
5752 }
5753
5754 int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
5755                                         GSupplicantInterfaceCallback callback,
5756                                         void *user_data)
5757 {
5758         struct p2p_service_data *data;
5759         int ret;
5760
5761         SUPPLICANT_DBG("");
5762
5763         if (!system_available)
5764                 return -EFAULT;
5765
5766         data = dbus_malloc0(sizeof(*data));
5767         data->service = p2p_service_params;
5768         data->callback = callback;
5769         data->user_data = user_data;
5770
5771         if (p2p_service_params->wfd_ies)
5772                 data->registration = true;
5773
5774         ret = supplicant_dbus_property_set(SUPPLICANT_PATH,
5775                                         SUPPLICANT_INTERFACE, "WFDIEs",
5776                                         DBUS_TYPE_ARRAY_AS_STRING
5777                                         DBUS_TYPE_BYTE_AS_STRING,
5778                                         widi_ies_params,
5779                                         interface_p2p_service_result,
5780                                         data, NULL);
5781         if (ret < 0 && ret != -EINPROGRESS) {
5782                 dbus_free(data);
5783                 return ret;
5784         }
5785
5786         return -EINPROGRESS;
5787 }
5788
5789 #if defined TIZEN_EXT
5790 int g_supplicant_interface_remove_network(GSupplicantInterface *interface)
5791 {
5792         struct interface_data *data;
5793
5794         SUPPLICANT_DBG("");
5795
5796         if (interface == NULL)
5797                 return -EINVAL;
5798
5799         if (system_available == FALSE)
5800                 return -EFAULT;
5801
5802         data = dbus_malloc0(sizeof(*data));
5803         if (data == NULL)
5804                 return -ENOMEM;
5805
5806         data->interface = interface;
5807
5808         return network_remove(data);
5809 }
5810 #endif
5811
5812 static const char *g_supplicant_rule0 = "type=signal,"
5813                                         "path=" DBUS_PATH_DBUS ","
5814                                         "sender=" DBUS_SERVICE_DBUS ","
5815                                         "interface=" DBUS_INTERFACE_DBUS ","
5816                                         "member=NameOwnerChanged,"
5817                                         "arg0=" SUPPLICANT_SERVICE;
5818 static const char *g_supplicant_rule1 = "type=signal,"
5819                         "interface=" SUPPLICANT_INTERFACE;
5820 static const char *g_supplicant_rule2 = "type=signal,"
5821                         "interface=" SUPPLICANT_INTERFACE ".Interface";
5822 static const char *g_supplicant_rule3 = "type=signal,"
5823                         "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
5824 static const char *g_supplicant_rule4 = "type=signal,"
5825                         "interface=" SUPPLICANT_INTERFACE ".BSS";
5826 static const char *g_supplicant_rule5 = "type=signal,"
5827                         "interface=" SUPPLICANT_INTERFACE ".Network";
5828 #if !defined TIZEN_EXT
5829 static const char *g_supplicant_rule6 = "type=signal,"
5830                 "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
5831 static const char *g_supplicant_rule7 = "type=signal,"
5832                 "interface=" SUPPLICANT_INTERFACE ".Peer";
5833 static const char *g_supplicant_rule8 = "type=signal,"
5834                 "interface=" SUPPLICANT_INTERFACE ".Group";
5835 #endif
5836
5837 static void invoke_introspect_method(void)
5838 {
5839         DBusMessage *message;
5840
5841         message = dbus_message_new_method_call(SUPPLICANT_SERVICE,
5842                                         SUPPLICANT_PATH,
5843                                         DBUS_INTERFACE_INTROSPECTABLE,
5844                                         "Introspect");
5845
5846         if (!message)
5847                 return;
5848
5849         dbus_message_set_no_reply(message, TRUE);
5850         dbus_connection_send(connection, message, NULL);
5851         dbus_message_unref(message);
5852 }
5853
5854 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
5855 {
5856         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
5857         if (!connection)
5858                 return -EIO;
5859
5860         if (!dbus_connection_add_filter(connection, g_supplicant_filter,
5861                                                 NULL, NULL)) {
5862                 dbus_connection_unref(connection);
5863                 connection = NULL;
5864                 return -EIO;
5865         }
5866
5867         callbacks_pointer = callbacks;
5868         eap_methods = 0;
5869
5870         interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
5871                                                 NULL, remove_interface);
5872
5873         bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
5874                                                                 NULL, NULL);
5875         peer_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
5876                                                                 NULL, NULL);
5877         group_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
5878                                                                 NULL, NULL);
5879         pending_peer_connection = g_hash_table_new_full(g_str_hash, g_str_equal,
5880                                                                 NULL, NULL);
5881
5882         supplicant_dbus_setup(connection);
5883
5884         dbus_bus_add_match(connection, g_supplicant_rule0, NULL);
5885         dbus_bus_add_match(connection, g_supplicant_rule1, NULL);
5886         dbus_bus_add_match(connection, g_supplicant_rule2, NULL);
5887         dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
5888         dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
5889         dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
5890 #if defined TIZEN_EXT
5891         dbus_bus_add_match(connection,
5892                         "type=signal,interface=org.tizen.system.deviced.PowerOff,"
5893                         "member=ChangeState", NULL);
5894 #endif
5895 #if !defined TIZEN_EXT
5896         dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
5897         dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
5898         dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
5899 #endif
5900         dbus_connection_flush(connection);
5901
5902         if (dbus_bus_name_has_owner(connection,
5903                                         SUPPLICANT_SERVICE, NULL)) {
5904                 system_available = TRUE;
5905                 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
5906                                                 SUPPLICANT_INTERFACE,
5907                                                 service_property, NULL, NULL);
5908         } else
5909                 invoke_introspect_method();
5910
5911         return 0;
5912 }
5913
5914 static void unregister_interface_remove_params(DBusMessageIter *iter,
5915                                                 void *user_data)
5916 {
5917         const char *path = user_data;
5918
5919         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
5920                                                         &path);
5921 }
5922
5923
5924 static void unregister_remove_interface(gpointer key, gpointer value,
5925                                                 gpointer user_data)
5926 {
5927         GSupplicantInterface *interface = value;
5928
5929         supplicant_dbus_method_call(SUPPLICANT_PATH,
5930                                         SUPPLICANT_INTERFACE,
5931                                         "RemoveInterface",
5932                                         unregister_interface_remove_params,
5933                                         NULL, interface->path, NULL);
5934 }
5935
5936 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
5937 {
5938         SUPPLICANT_DBG("");
5939
5940         if (connection) {
5941 #if !defined TIZEN_EXT
5942                 dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
5943                 dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
5944                 dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
5945 #endif
5946                 dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
5947                 dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
5948                 dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
5949                 dbus_bus_remove_match(connection, g_supplicant_rule2, NULL);
5950                 dbus_bus_remove_match(connection, g_supplicant_rule1, NULL);
5951                 dbus_bus_remove_match(connection, g_supplicant_rule0, NULL);
5952                 dbus_connection_flush(connection);
5953
5954                 dbus_connection_remove_filter(connection,
5955                                                 g_supplicant_filter, NULL);
5956         }
5957
5958         if (bss_mapping) {
5959                 g_hash_table_destroy(bss_mapping);
5960                 bss_mapping = NULL;
5961         }
5962
5963         if (peer_mapping) {
5964                 g_hash_table_destroy(peer_mapping);
5965                 peer_mapping = NULL;
5966         }
5967
5968         if (group_mapping) {
5969                 g_hash_table_destroy(group_mapping);
5970                 group_mapping = NULL;
5971         }
5972
5973         if (interface_table) {
5974                 g_hash_table_foreach(interface_table,
5975                                         unregister_remove_interface, NULL);
5976                 g_hash_table_destroy(interface_table);
5977                 interface_table = NULL;
5978         }
5979
5980         if (system_available)
5981                 callback_system_killed();
5982
5983         if (connection) {
5984                 dbus_connection_unref(connection);
5985                 connection = NULL;
5986         }
5987
5988         callbacks_pointer = NULL;
5989         eap_methods = 0;
5990 }