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