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