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