Implement control request replies for the D-Bus interface
[mech_eap.git] / wpa_supplicant / dbus / dbus_new.c
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
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  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "wps/wps.h"
22 #include "../config.h"
23 #include "../wpa_supplicant_i.h"
24 #include "../bss.h"
25 #include "../wpas_glue.h"
26 #include "dbus_new_helpers.h"
27 #include "dbus_dict_helpers.h"
28 #include "dbus_new.h"
29 #include "dbus_new_handlers.h"
30 #include "dbus_common.h"
31 #include "dbus_common_i.h"
32 #include "dbus_new_handlers_p2p.h"
33 #include "p2p/p2p.h"
34
35
36 /**
37  * wpas_dbus_signal_interface - Send a interface related event signal
38  * @wpa_s: %wpa_supplicant network interface data
39  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
40  * @properties: Whether to add second argument with object properties
41  *
42  * Notify listeners about event related with interface
43  */
44 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
45                                        const char *sig_name, int properties)
46 {
47         struct wpas_dbus_priv *iface;
48         DBusMessage *msg;
49         DBusMessageIter iter;
50
51         iface = wpa_s->global->dbus;
52
53         /* Do nothing if the control interface is not turned on */
54         if (iface == NULL)
55                 return;
56
57         msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
58                                       WPAS_DBUS_NEW_INTERFACE, sig_name);
59         if (msg == NULL)
60                 return;
61
62         dbus_message_iter_init_append(msg, &iter);
63         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
64                                             &wpa_s->dbus_new_path))
65                 goto err;
66
67         if (properties) {
68                 if (!wpa_dbus_get_object_properties(
69                             iface, wpa_s->dbus_new_path,
70                             WPAS_DBUS_NEW_IFACE_INTERFACE, &iter))
71                         goto err;
72         }
73
74         dbus_connection_send(iface->con, msg, NULL);
75         dbus_message_unref(msg);
76         return;
77
78 err:
79         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
80         dbus_message_unref(msg);
81 }
82
83
84 /**
85  * wpas_dbus_signal_interface_added - Send a interface created signal
86  * @wpa_s: %wpa_supplicant network interface data
87  *
88  * Notify listeners about creating new interface
89  */
90 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
91 {
92         wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
93 }
94
95
96 /**
97  * wpas_dbus_signal_interface_removed - Send a interface removed signal
98  * @wpa_s: %wpa_supplicant network interface data
99  *
100  * Notify listeners about removing interface
101  */
102 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
103 {
104         wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
105
106 }
107
108
109 /**
110  * wpas_dbus_signal_scan_done - send scan done signal
111  * @wpa_s: %wpa_supplicant network interface data
112  * @success: indicates if scanning succeed or failed
113  *
114  * Notify listeners about finishing a scan
115  */
116 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
117 {
118         struct wpas_dbus_priv *iface;
119         DBusMessage *msg;
120         dbus_bool_t succ;
121
122         iface = wpa_s->global->dbus;
123
124         /* Do nothing if the control interface is not turned on */
125         if (iface == NULL)
126                 return;
127
128         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
129                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
130                                       "ScanDone");
131         if (msg == NULL)
132                 return;
133
134         succ = success ? TRUE : FALSE;
135         if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
136                                      DBUS_TYPE_INVALID))
137                 dbus_connection_send(iface->con, msg, NULL);
138         else
139                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
140         dbus_message_unref(msg);
141 }
142
143
144 /**
145  * wpas_dbus_signal_blob - Send a BSS related event signal
146  * @wpa_s: %wpa_supplicant network interface data
147  * @bss_obj_path: BSS object path
148  * @sig_name: signal name - BSSAdded or BSSRemoved
149  * @properties: Whether to add second argument with object properties
150  *
151  * Notify listeners about event related with BSS
152  */
153 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
154                                  const char *bss_obj_path,
155                                  const char *sig_name, int properties)
156 {
157         struct wpas_dbus_priv *iface;
158         DBusMessage *msg;
159         DBusMessageIter iter;
160
161         iface = wpa_s->global->dbus;
162
163         /* Do nothing if the control interface is not turned on */
164         if (iface == NULL)
165                 return;
166
167         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
168                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
169                                       sig_name);
170         if (msg == NULL)
171                 return;
172
173         dbus_message_iter_init_append(msg, &iter);
174         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
175                                             &bss_obj_path))
176                 goto err;
177
178         if (properties) {
179                 if (!wpa_dbus_get_object_properties(iface, bss_obj_path,
180                                                     WPAS_DBUS_NEW_IFACE_BSS,
181                                                     &iter))
182                         goto err;
183         }
184
185         dbus_connection_send(iface->con, msg, NULL);
186         dbus_message_unref(msg);
187         return;
188
189 err:
190         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
191         dbus_message_unref(msg);
192 }
193
194
195 /**
196  * wpas_dbus_signal_bss_added - Send a BSS added signal
197  * @wpa_s: %wpa_supplicant network interface data
198  * @bss_obj_path: new BSS object path
199  *
200  * Notify listeners about adding new BSS
201  */
202 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
203                                        const char *bss_obj_path)
204 {
205         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
206 }
207
208
209 /**
210  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
211  * @wpa_s: %wpa_supplicant network interface data
212  * @bss_obj_path: BSS object path
213  *
214  * Notify listeners about removing BSS
215  */
216 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
217                                          const char *bss_obj_path)
218 {
219         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
220 }
221
222
223 /**
224  * wpas_dbus_signal_blob - Send a blob related event signal
225  * @wpa_s: %wpa_supplicant network interface data
226  * @name: blob name
227  * @sig_name: signal name - BlobAdded or BlobRemoved
228  *
229  * Notify listeners about event related with blob
230  */
231 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
232                                   const char *name, const char *sig_name)
233 {
234         struct wpas_dbus_priv *iface;
235         DBusMessage *msg;
236
237         iface = wpa_s->global->dbus;
238
239         /* Do nothing if the control interface is not turned on */
240         if (iface == NULL)
241                 return;
242
243         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
244                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
245                                       sig_name);
246         if (msg == NULL)
247                 return;
248
249         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
250                                      DBUS_TYPE_INVALID))
251                 dbus_connection_send(iface->con, msg, NULL);
252         else
253                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
254         dbus_message_unref(msg);
255 }
256
257
258 /**
259  * wpas_dbus_signal_blob_added - Send a blob added signal
260  * @wpa_s: %wpa_supplicant network interface data
261  * @name: blob name
262  *
263  * Notify listeners about adding a new blob
264  */
265 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
266                                  const char *name)
267 {
268         wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
269 }
270
271
272 /**
273  * wpas_dbus_signal_blob_removed - Send a blob removed signal
274  * @wpa_s: %wpa_supplicant network interface data
275  * @name: blob name
276  *
277  * Notify listeners about removing blob
278  */
279 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
280                                    const char *name)
281 {
282         wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
283 }
284
285
286 /**
287  * wpas_dbus_signal_network - Send a network related event signal
288  * @wpa_s: %wpa_supplicant network interface data
289  * @id: new network id
290  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
291  * @properties: determines if add second argument with object properties
292  *
293  * Notify listeners about event related with configured network
294  */
295 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
296                                      int id, const char *sig_name,
297                                      int properties)
298 {
299         struct wpas_dbus_priv *iface;
300         DBusMessage *msg;
301         DBusMessageIter iter;
302         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
303
304         iface = wpa_s->global->dbus;
305
306         /* Do nothing if the control interface is not turned on */
307         if (iface == NULL)
308                 return;
309
310         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
311                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
312                     wpa_s->dbus_new_path, id);
313
314         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
315                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
316                                       sig_name);
317         if (msg == NULL)
318                 return;
319
320         dbus_message_iter_init_append(msg, &iter);
321         path = net_obj_path;
322         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
323                                             &path))
324                 goto err;
325
326         if (properties) {
327                 if (!wpa_dbus_get_object_properties(
328                             iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
329                             &iter))
330                         goto err;
331         }
332
333         dbus_connection_send(iface->con, msg, NULL);
334
335         dbus_message_unref(msg);
336         return;
337
338 err:
339         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
340         dbus_message_unref(msg);
341 }
342
343
344 /**
345  * wpas_dbus_signal_network_added - Send a network added signal
346  * @wpa_s: %wpa_supplicant network interface data
347  * @id: new network id
348  *
349  * Notify listeners about adding new network
350  */
351 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
352                                            int id)
353 {
354         wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
355 }
356
357
358 /**
359  * wpas_dbus_signal_network_removed - Send a network removed signal
360  * @wpa_s: %wpa_supplicant network interface data
361  * @id: network id
362  *
363  * Notify listeners about removing a network
364  */
365 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
366                                              int id)
367 {
368         wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
369 }
370
371
372 /**
373  * wpas_dbus_signal_network_selected - Send a network selected signal
374  * @wpa_s: %wpa_supplicant network interface data
375  * @id: network id
376  *
377  * Notify listeners about selecting a network
378  */
379 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
380 {
381         wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
382 }
383
384
385 /**
386  * wpas_dbus_signal_network_request - Indicate that additional information
387  * (EAP password, etc.) is required to complete the association to this SSID
388  * @wpa_s: %wpa_supplicant network interface data
389  * @rtype: The specific additional information required
390  * @default_text: Optional description of required information
391  *
392  * Request additional information or passwords to complete an association
393  * request.
394  */
395 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
396                                       struct wpa_ssid *ssid,
397                                       enum wpa_ctrl_req_type rtype,
398                                       const char *default_txt)
399 {
400         struct wpas_dbus_priv *iface;
401         DBusMessage *msg;
402         DBusMessageIter iter;
403         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
404         const char *field, *txt = NULL, *net_ptr;
405
406         iface = wpa_s->global->dbus;
407
408         /* Do nothing if the control interface is not turned on */
409         if (iface == NULL)
410                 return;
411
412         field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
413         if (field == NULL)
414                 return;
415
416         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
417                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
418                                       "NetworkRequest");
419         if (msg == NULL)
420                 return;
421
422         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
423                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
424                     wpa_s->dbus_new_path, ssid->id);
425         net_ptr = &net_obj_path[0];
426
427         dbus_message_iter_init_append(msg, &iter);
428         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
429                                             &net_ptr))
430                 goto err;
431         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field))
432                 goto err;
433         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
434                 goto err;
435
436         dbus_connection_send(iface->con, msg, NULL);
437         dbus_message_unref(msg);
438         return;
439
440 err:
441         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
442         dbus_message_unref(msg);
443 }
444
445
446 /**
447  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
448  * @wpa_s: %wpa_supplicant network interface data
449  * @ssid: configured network which Enabled property has changed
450  *
451  * Sends PropertyChanged signals containing new value of Enabled property
452  * for specified network
453  */
454 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
455                                               struct wpa_ssid *ssid)
456 {
457
458         char path[WPAS_DBUS_OBJECT_PATH_MAX];
459         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
460                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
461                     wpa_s->dbus_new_path, ssid->id);
462
463         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
464                                        WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
465 }
466
467
468 #ifdef CONFIG_WPS
469
470 /**
471  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
472  * @wpa_s: %wpa_supplicant network interface data
473  *
474  * Sends Event dbus signal with name "success" and empty dict as arguments
475  */
476 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
477 {
478
479         DBusMessage *msg;
480         DBusMessageIter iter, dict_iter;
481         struct wpas_dbus_priv *iface;
482         char *key = "success";
483
484         iface = wpa_s->global->dbus;
485
486         /* Do nothing if the control interface is not turned on */
487         if (iface == NULL)
488                 return;
489
490         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
491                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
492         if (msg == NULL)
493                 return;
494
495         dbus_message_iter_init_append(msg, &iter);
496
497         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
498             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
499             !wpa_dbus_dict_close_write(&iter, &dict_iter))
500                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
501         else
502                 dbus_connection_send(iface->con, msg, NULL);
503
504         dbus_message_unref(msg);
505 }
506
507
508 /**
509  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
510  * @wpa_s: %wpa_supplicant network interface data
511  *
512  * Sends Event dbus signal with name "fail" and dictionary containing
513  * "msg field with fail message number (int32) as arguments
514  */
515 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
516                                      struct wps_event_fail *fail)
517 {
518
519         DBusMessage *msg;
520         DBusMessageIter iter, dict_iter;
521         struct wpas_dbus_priv *iface;
522         char *key = "fail";
523
524         iface = wpa_s->global->dbus;
525
526         /* Do nothing if the control interface is not turned on */
527         if (iface == NULL)
528                 return;
529
530         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
531                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
532         if (msg == NULL)
533                 return;
534
535         dbus_message_iter_init_append(msg, &iter);
536
537         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
538             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
539             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
540             !wpa_dbus_dict_close_write(&iter, &dict_iter))
541                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
542         else
543                 dbus_connection_send(iface->con, msg, NULL);
544
545         dbus_message_unref(msg);
546 }
547
548
549 /**
550  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
551  * @wpa_s: %wpa_supplicant network interface data
552  *
553  * Sends Event dbus signal with name "m2d" and dictionary containing
554  * fields of wps_event_m2d structure.
555  */
556 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
557                                     struct wps_event_m2d *m2d)
558 {
559
560         DBusMessage *msg;
561         DBusMessageIter iter, dict_iter;
562         struct wpas_dbus_priv *iface;
563         char *key = "m2d";
564
565         iface = wpa_s->global->dbus;
566
567         /* Do nothing if the control interface is not turned on */
568         if (iface == NULL)
569                 return;
570
571         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
572                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
573         if (msg == NULL)
574                 return;
575
576         dbus_message_iter_init_append(msg, &iter);
577
578         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
579             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
580             !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
581                                          m2d->config_methods) ||
582             !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
583                                              (const char *) m2d->manufacturer,
584                                              m2d->manufacturer_len) ||
585             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
586                                              (const char *) m2d->model_name,
587                                              m2d->model_name_len) ||
588             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
589                                              (const char *) m2d->model_number,
590                                              m2d->model_number_len) ||
591             !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
592                                              (const char *)
593                                              m2d->serial_number,
594                                              m2d->serial_number_len) ||
595             !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
596                                              (const char *) m2d->dev_name,
597                                              m2d->dev_name_len) ||
598             !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
599                                              (const char *)
600                                              m2d->primary_dev_type, 8) ||
601             !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
602                                          m2d->config_error) ||
603             !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
604                                          m2d->dev_password_id) ||
605             !wpa_dbus_dict_close_write(&iter, &dict_iter))
606                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
607         else
608                 dbus_connection_send(iface->con, msg, NULL);
609
610         dbus_message_unref(msg);
611 }
612
613
614 /**
615  * wpas_dbus_signal_wps_cred - Signals new credentials
616  * @wpa_s: %wpa_supplicant network interface data
617  *
618  * Sends signal with credentials in directory argument
619  */
620 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
621                                const struct wps_credential *cred)
622 {
623         DBusMessage *msg;
624         DBusMessageIter iter, dict_iter;
625         struct wpas_dbus_priv *iface;
626         char *auth_type[6]; /* we have six possible authorization types */
627         int at_num = 0;
628         char *encr_type[4]; /* we have four possible encryption types */
629         int et_num = 0;
630
631         iface = wpa_s->global->dbus;
632
633         /* Do nothing if the control interface is not turned on */
634         if (iface == NULL)
635                 return;
636
637         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
638                                       WPAS_DBUS_NEW_IFACE_WPS,
639                                       "Credentials");
640         if (msg == NULL)
641                 return;
642
643         dbus_message_iter_init_append(msg, &iter);
644         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
645                 goto nomem;
646
647         if (cred->auth_type & WPS_AUTH_OPEN)
648                 auth_type[at_num++] = "open";
649         if (cred->auth_type & WPS_AUTH_WPAPSK)
650                 auth_type[at_num++] = "wpa-psk";
651         if (cred->auth_type & WPS_AUTH_SHARED)
652                 auth_type[at_num++] = "shared";
653         if (cred->auth_type & WPS_AUTH_WPA)
654                 auth_type[at_num++] = "wpa-eap";
655         if (cred->auth_type & WPS_AUTH_WPA2)
656                 auth_type[at_num++] = "wpa2-eap";
657         if (cred->auth_type & WPS_AUTH_WPA2PSK)
658                 auth_type[at_num++] =
659                 "wpa2-psk";
660
661         if (cred->encr_type & WPS_ENCR_NONE)
662                 encr_type[et_num++] = "none";
663         if (cred->encr_type & WPS_ENCR_WEP)
664                 encr_type[et_num++] = "wep";
665         if (cred->encr_type & WPS_ENCR_TKIP)
666                 encr_type[et_num++] = "tkip";
667         if (cred->encr_type & WPS_ENCR_AES)
668                 encr_type[et_num++] = "aes";
669
670         if (wpa_s->current_ssid) {
671                 if (!wpa_dbus_dict_append_byte_array(
672                             &dict_iter, "BSSID",
673                             (const char *) wpa_s->current_ssid->bssid,
674                             ETH_ALEN))
675                         goto nomem;
676         }
677
678         if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
679                                              (const char *) cred->ssid,
680                                              cred->ssid_len) ||
681             !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
682                                                (const char **) auth_type,
683                                                at_num) ||
684             !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
685                                                (const char **) encr_type,
686                                                et_num) ||
687             !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
688                                              (const char *) cred->key,
689                                              cred->key_len) ||
690             !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
691                                          cred->key_idx) ||
692             !wpa_dbus_dict_close_write(&iter, &dict_iter))
693                 goto nomem;
694
695         dbus_connection_send(iface->con, msg, NULL);
696
697 nomem:
698         dbus_message_unref(msg);
699 }
700
701 #endif /* CONFIG_WPS */
702
703 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
704                                     int depth, const char *subject,
705                                     const char *cert_hash,
706                                     const struct wpabuf *cert)
707 {
708         struct wpas_dbus_priv *iface;
709         DBusMessage *msg;
710         DBusMessageIter iter, dict_iter;
711
712         iface = wpa_s->global->dbus;
713
714         /* Do nothing if the control interface is not turned on */
715         if (iface == NULL)
716                 return;
717
718         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
719                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
720                                       "Certification");
721         if (msg == NULL)
722                 return;
723
724         dbus_message_iter_init_append(msg, &iter);
725         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
726                 goto nomem;
727
728         if (!wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
729             !wpa_dbus_dict_append_string(&dict_iter, "subject", subject))
730                 goto nomem;
731
732         if (cert_hash &&
733             !wpa_dbus_dict_append_string(&dict_iter, "cert_hash", cert_hash))
734                 goto nomem;
735
736         if (cert &&
737             !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
738                                              wpabuf_head(cert),
739                                              wpabuf_len(cert)))
740                 goto nomem;
741
742         if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
743                 goto nomem;
744
745         dbus_connection_send(iface->con, msg, NULL);
746
747 nomem:
748         dbus_message_unref(msg);
749 }
750
751 #ifdef CONFIG_P2P
752
753 /**
754  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
755  * @wpa_s: %wpa_supplicant network interface data
756  * @role: role of this device (client or GO)
757  * Sends signal with i/f name and role as string arguments
758  */
759 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
760                                         const char *role)
761 {
762
763         DBusMessage *msg;
764         DBusMessageIter iter;
765         struct wpas_dbus_priv *iface = wpa_s->global->dbus;
766         char *ifname = wpa_s->ifname;
767
768         /* Do nothing if the control interface is not turned on */
769         if (iface == NULL)
770                 return;
771
772         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
773                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
774                                       "GroupFinished");
775         if (msg == NULL)
776                 return;
777
778         dbus_message_iter_init_append(msg, &iter);
779
780         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
781                 wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
782                                       "signal -not enough memory for ifname ");
783                 goto err;
784         }
785
786         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
787                 wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
788                                       "signal -not enough memory for role ");
789         else
790                 dbus_connection_send(iface->con, msg, NULL);
791
792 err:
793         dbus_message_unref(msg);
794 }
795
796
797 /**
798  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
799  *
800  * @dev_addr - who sent the request or responded to our request.
801  * @request - Will be 1 if request, 0 for response.
802  * @status - valid only in case of response
803  * @config_methods - wps config methods
804  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
805  *
806  * Sends following provision discovery related events:
807  *      ProvisionDiscoveryRequestDisplayPin
808  *      ProvisionDiscoveryResponseDisplayPin
809  *      ProvisionDiscoveryRequestEnterPin
810  *      ProvisionDiscoveryResponseEnterPin
811  *      ProvisionDiscoveryPBCRequest
812  *      ProvisionDiscoveryPBCResponse
813  *
814  *      TODO::
815  *      ProvisionDiscoveryFailure (timeout case)
816  */
817 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
818                                               const u8 *dev_addr, int request,
819                                               enum p2p_prov_disc_status status,
820                                               u16 config_methods,
821                                               unsigned int generated_pin)
822 {
823         DBusMessage *msg;
824         DBusMessageIter iter;
825         struct wpas_dbus_priv *iface;
826         char *_signal;
827         int add_pin = 0;
828         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
829         int error_ret = 1;
830         char pin[9], *p_pin = NULL;
831
832         iface = wpa_s->global->dbus;
833
834         /* Do nothing if the control interface is not turned on */
835         if (iface == NULL)
836                 return;
837
838         if (request || !status) {
839                 if (config_methods & WPS_CONFIG_DISPLAY)
840                         _signal = request ?
841                                  "ProvisionDiscoveryRequestDisplayPin" :
842                                  "ProvisionDiscoveryResponseEnterPin";
843                 else if (config_methods & WPS_CONFIG_KEYPAD)
844                         _signal = request ?
845                                  "ProvisionDiscoveryRequestEnterPin" :
846                                  "ProvisionDiscoveryResponseDisplayPin";
847                 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
848                         _signal = request ? "ProvisionDiscoveryPBCRequest" :
849                                    "ProvisionDiscoveryPBCResponse";
850                 else
851                         return; /* Unknown or un-supported method */
852         } else if (!request && status)
853                 /* Explicit check for failure response */
854                 _signal = "ProvisionDiscoveryFailure";
855
856         add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
857                    (!request && !status &&
858                         (config_methods & WPS_CONFIG_KEYPAD)));
859
860         if (add_pin) {
861                 os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
862                 p_pin = pin;
863         }
864
865         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
866                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
867         if (msg == NULL)
868                 return;
869
870         /* Check if this is a known peer */
871         if (p2p_get_peer_info(wpa_s->global->p2p, dev_addr, 0, NULL, 0) < 0)
872                 goto error;
873
874         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
875                         "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
876                         COMPACT_MACSTR,
877                         wpa_s->dbus_new_path, MAC2STR(dev_addr));
878
879         path = peer_obj_path;
880
881         dbus_message_iter_init_append(msg, &iter);
882
883         if (!dbus_message_iter_append_basic(&iter,
884                                             DBUS_TYPE_OBJECT_PATH,
885                                             &path))
886                         goto error;
887
888         if (!request && status)
889                 /* Attach status to ProvisionDiscoveryFailure */
890                 error_ret = !dbus_message_iter_append_basic(&iter,
891                                                     DBUS_TYPE_INT32,
892                                                     &status);
893         else
894                 error_ret = (add_pin &&
895                                  !dbus_message_iter_append_basic(&iter,
896                                                         DBUS_TYPE_STRING,
897                                                         &p_pin));
898
899 error:
900         if (!error_ret)
901                 dbus_connection_send(iface->con, msg, NULL);
902         else
903                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
904
905         dbus_message_unref(msg);
906 }
907
908
909 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
910                                      const u8 *src, u16 dev_passwd_id)
911 {
912         DBusMessage *msg;
913         DBusMessageIter iter;
914         struct wpas_dbus_priv *iface;
915         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
916
917         iface = wpa_s->global->dbus;
918
919         /* Do nothing if the control interface is not turned on */
920         if (iface == NULL)
921                 return;
922
923         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
924                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
925                     wpa_s->dbus_new_path, MAC2STR(src));
926         path = peer_obj_path;
927
928         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
929                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
930                                       "GONegotiationRequest");
931         if (msg == NULL)
932                 return;
933
934         dbus_message_iter_init_append(msg, &iter);
935
936         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
937                                             &path) ||
938             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
939                                             &dev_passwd_id))
940                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
941         else
942                 dbus_connection_send(iface->con, msg, NULL);
943
944         dbus_message_unref(msg);
945 }
946
947
948 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
949                                         const struct wpa_ssid *ssid,
950                                         char *group_obj_path)
951 {
952         char group_name[3];
953
954         if (os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
955                 return -1;
956
957         memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
958         group_name[2] = '\0';
959
960         os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
961                     "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
962                     wpa_s->dbus_new_path, group_name);
963
964         return 0;
965 }
966
967
968 /**
969  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
970  * started. Emitted when a group is successfully started
971  * irrespective of the role (client/GO) of the current device
972  *
973  * @wpa_s: %wpa_supplicant network interface data
974  * @ssid: SSID object
975  * @client: this device is P2P client
976  * @network_id: network id of the group started, use instead of ssid->id
977  *      to account for persistent groups
978  */
979 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
980                                         const struct wpa_ssid *ssid,
981                                         int client, int network_id)
982 {
983         DBusMessage *msg;
984         DBusMessageIter iter, dict_iter;
985         struct wpas_dbus_priv *iface;
986         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
987         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
988
989         iface = wpa_s->parent->global->dbus;
990
991         /* Do nothing if the control interface is not turned on */
992         if (iface == NULL)
993                 return;
994
995         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
996                 return;
997
998         /* New interface has been created for this group */
999         msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
1000                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1001                                       "GroupStarted");
1002
1003         if (msg == NULL)
1004                 return;
1005
1006         dbus_message_iter_init_append(msg, &iter);
1007         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1008                 goto nomem;
1009
1010         /*
1011          * In case the device supports creating a separate interface the
1012          * DBus client will need to know the object path for the interface
1013          * object this group was created on, so include it here.
1014          */
1015         if (!wpa_dbus_dict_append_object_path(&dict_iter,
1016                                         "interface_object",
1017                                         wpa_s->dbus_new_path))
1018                 goto nomem;
1019
1020         if (!wpa_dbus_dict_append_string(&dict_iter, "role",
1021                                          client ? "client" : "GO"))
1022                 goto nomem;
1023
1024         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1025                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1026                     wpa_s->parent->dbus_new_path, network_id);
1027
1028         if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1029                                              group_obj_path) ||
1030            !wpa_dbus_dict_append_object_path(&dict_iter, "network_object",
1031                                              net_obj_path) ||
1032            !wpa_dbus_dict_close_write(&iter, &dict_iter))
1033                 goto nomem;
1034
1035         dbus_connection_send(iface->con, msg, NULL);
1036
1037 nomem:
1038         dbus_message_unref(msg);
1039 }
1040
1041
1042 /**
1043  *
1044  * Method to emit GONeogtiation Success or Failure signals based
1045  * on status.
1046  * @status: Status of the GO neg request. 0 for success, other for errors.
1047  */
1048 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status)
1049 {
1050         DBusMessage *msg;
1051         DBusMessageIter iter;
1052         struct wpas_dbus_priv *iface;
1053
1054         iface = wpa_s->global->dbus;
1055
1056         /* Do nothing if the control interface is not turned on */
1057         if (iface == NULL)
1058                 return;
1059
1060         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1061                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1062                                       status ? "GONegotiationFailure" :
1063                                                "GONegotiationSuccess");
1064         if (msg == NULL)
1065                 return;
1066
1067         if (status) {
1068                 dbus_message_iter_init_append(msg, &iter);
1069                 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
1070                                                     &status)) {
1071                         wpa_printf(MSG_ERROR,
1072                                    "dbus: Failed to construct signal");
1073                         goto err;
1074                 }
1075         }
1076
1077         dbus_connection_send(iface->con, msg, NULL);
1078 err:
1079         dbus_message_unref(msg);
1080 }
1081
1082
1083 /**
1084  *
1085  * Method to emit Invitation Result signal based on status and
1086  * bssid
1087  * @status: Status of the Invite request. 0 for success, other
1088  * for errors
1089  * @bssid : Basic Service Set Identifier
1090  */
1091 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1092                                             int status, const u8 *bssid)
1093 {
1094         DBusMessage *msg;
1095         DBusMessageIter iter, dict_iter;
1096         struct wpas_dbus_priv *iface;
1097
1098         wpa_printf(MSG_INFO, "%s\n", __func__);
1099
1100         iface = wpa_s->global->dbus;
1101         /* Do nothing if the control interface is not turned on */
1102         if (iface == NULL)
1103                 return;
1104
1105         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1106                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1107                                       "InvitationResult");
1108
1109         if (msg == NULL)
1110                 return;
1111
1112         dbus_message_iter_init_append(msg, &iter);
1113         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1114                 goto nomem;
1115
1116         if (!wpa_dbus_dict_append_int32(&dict_iter, "status", status))
1117                 goto nomem;
1118         if (bssid) {
1119                 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1120                                                      (const char *) bssid,
1121                                                      ETH_ALEN))
1122                         goto nomem;
1123         }
1124         if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1125                 goto nomem;
1126
1127         dbus_connection_send(iface->con, msg, NULL);
1128
1129 nomem:
1130         dbus_message_unref(msg);
1131 }
1132
1133
1134 /**
1135  *
1136  * Method to emit a signal for a peer joining the group.
1137  * The signal will carry path to the group member object
1138  * constructed using p2p i/f addr used for connecting.
1139  *
1140  * @wpa_s: %wpa_supplicant network interface data
1141  * @member_addr: addr (p2p i/f) of the peer joining the group
1142  */
1143 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1144                                       const u8 *member)
1145 {
1146         struct wpas_dbus_priv *iface;
1147         DBusMessage *msg;
1148         DBusMessageIter iter;
1149         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1150
1151         iface = wpa_s->global->dbus;
1152
1153         /* Do nothing if the control interface is not turned on */
1154         if (iface == NULL)
1155                 return;
1156
1157         if (!wpa_s->dbus_groupobj_path)
1158                 return;
1159
1160         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1161                         "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1162                         COMPACT_MACSTR,
1163                         wpa_s->dbus_groupobj_path, MAC2STR(member));
1164
1165         msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1166                                       WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1167                                       "PeerJoined");
1168         if (msg == NULL)
1169                 return;
1170
1171         dbus_message_iter_init_append(msg, &iter);
1172         path = groupmember_obj_path;
1173         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1174                                             &path))
1175                 goto err;
1176
1177         dbus_connection_send(iface->con, msg, NULL);
1178
1179         dbus_message_unref(msg);
1180         return;
1181
1182 err:
1183         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1184         dbus_message_unref(msg);
1185 }
1186
1187
1188 /**
1189  *
1190  * Method to emit a signal for a peer disconnecting the group.
1191  * The signal will carry path to the group member object
1192  * constructed using p2p i/f addr used for connecting.
1193  *
1194  * @wpa_s: %wpa_supplicant network interface data
1195  * @member_addr: addr (p2p i/f) of the peer joining the group
1196  */
1197 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1198                                       const u8 *member)
1199 {
1200         struct wpas_dbus_priv *iface;
1201         DBusMessage *msg;
1202         DBusMessageIter iter;
1203         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1204
1205         iface = wpa_s->global->dbus;
1206
1207         /* Do nothing if the control interface is not turned on */
1208         if (iface == NULL)
1209                 return;
1210
1211         if (!wpa_s->dbus_groupobj_path)
1212                 return;
1213
1214         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1215                         "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1216                         COMPACT_MACSTR,
1217                         wpa_s->dbus_groupobj_path, MAC2STR(member));
1218
1219         msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1220                                       WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1221                                       "PeerDisconnected");
1222         if (msg == NULL)
1223                 return;
1224
1225         dbus_message_iter_init_append(msg, &iter);
1226         path = groupmember_obj_path;
1227         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1228                                             &path))
1229                 goto err;
1230
1231         dbus_connection_send(iface->con, msg, NULL);
1232
1233         dbus_message_unref(msg);
1234         return;
1235
1236 err:
1237         wpa_printf(MSG_ERROR, "dbus: Failed to construct PeerDisconnected "
1238                               "signal");
1239         dbus_message_unref(msg);
1240 }
1241
1242
1243 /**
1244  *
1245  * Method to emit a signal for a service discovery request.
1246  * The signal will carry station address, frequency, dialog token,
1247  * update indicator and it tlvs
1248  *
1249  * @wpa_s: %wpa_supplicant network interface data
1250  * @sa: station addr (p2p i/f) of the peer
1251  * @dialog_token: service discovery request dialog token
1252  * @update_indic: service discovery request update indicator
1253  * @tlvs: service discovery request genrated byte array of tlvs
1254  * @tlvs_len: service discovery request tlvs length
1255  */
1256 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1257                                      int freq, const u8 *sa, u8 dialog_token,
1258                                      u16 update_indic, const u8 *tlvs,
1259                                      size_t tlvs_len)
1260 {
1261         DBusMessage *msg;
1262         DBusMessageIter iter, dict_iter;
1263         struct wpas_dbus_priv *iface;
1264         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1265         iface = wpa_s->global->dbus;
1266
1267         /* Do nothing if the control interface is not turned on */
1268         if (iface == NULL)
1269                 return;
1270
1271         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1272                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1273                                       "ServiceDiscoveryRequest");
1274         if (msg == NULL)
1275                 return;
1276
1277         /* Check if this is a known peer */
1278         if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0)
1279                 goto error;
1280
1281         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1282                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1283                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1284
1285         path = peer_obj_path;
1286
1287         dbus_message_iter_init_append(msg, &iter);
1288         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1289                 goto error;
1290
1291
1292         if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1293                                               path) ||
1294             !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1295             !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1296                                         dialog_token) ||
1297             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1298                                          update_indic) ||
1299             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1300                                              (const char *) tlvs,
1301                                              tlvs_len) ||
1302             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1303                 goto error;
1304
1305         dbus_connection_send(iface->con, msg, NULL);
1306         dbus_message_unref(msg);
1307         return;
1308 error:
1309         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1310         dbus_message_unref(msg);
1311 }
1312
1313
1314 /**
1315  *
1316  * Method to emit a signal for a service discovery response.
1317  * The signal will carry station address, update indicator and it
1318  * tlvs
1319  *
1320  * @wpa_s: %wpa_supplicant network interface data
1321  * @sa: station addr (p2p i/f) of the peer
1322  * @update_indic: service discovery request update indicator
1323  * @tlvs: service discovery request genrated byte array of tlvs
1324  * @tlvs_len: service discovery request tlvs length
1325  */
1326 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1327                                       const u8 *sa, u16 update_indic,
1328                                       const u8 *tlvs, size_t tlvs_len)
1329 {
1330         DBusMessage *msg;
1331         DBusMessageIter iter, dict_iter;
1332         struct wpas_dbus_priv *iface;
1333         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1334         iface = wpa_s->global->dbus;
1335
1336         /* Do nothing if the control interface is not turned on */
1337         if (iface == NULL)
1338                 return;
1339
1340         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1341                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1342                                 "ServiceDiscoveryResponse");
1343         if (msg == NULL)
1344                 return;
1345
1346         /* Check if this is a known peer */
1347         if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0)
1348                 goto error;
1349
1350         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1351                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1352                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1353
1354         path = peer_obj_path;
1355
1356         dbus_message_iter_init_append(msg, &iter);
1357         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1358                 goto error;
1359
1360         if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1361                                               path) ||
1362             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1363                                          update_indic) ||
1364             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1365                                              (const char *) tlvs,
1366                                              tlvs_len) ||
1367             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1368                 goto error;
1369
1370
1371         dbus_connection_send(iface->con, msg, NULL);
1372         dbus_message_unref(msg);
1373         return;
1374 error:
1375         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1376         dbus_message_unref(msg);
1377 }
1378
1379 /**
1380  * wpas_dbus_signal_persistent_group - Send a persistent group related
1381  *      event signal
1382  * @wpa_s: %wpa_supplicant network interface data
1383  * @id: new persistent group id
1384  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1385  * @properties: determines if add second argument with object properties
1386  *
1387  * Notify listeners about an event related to persistent groups.
1388  */
1389 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1390                                               int id, const char *sig_name,
1391                                               int properties)
1392 {
1393         struct wpas_dbus_priv *iface;
1394         DBusMessage *msg;
1395         DBusMessageIter iter;
1396         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1397
1398         iface = wpa_s->global->dbus;
1399
1400         /* Do nothing if the control interface is not turned on */
1401         if (iface == NULL)
1402                 return;
1403
1404         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1405                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1406                     wpa_s->dbus_new_path, id);
1407
1408         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1409                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1410                                       sig_name);
1411         if (msg == NULL)
1412                 return;
1413
1414         dbus_message_iter_init_append(msg, &iter);
1415         path = pgrp_obj_path;
1416         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1417                                             &path))
1418                 goto err;
1419
1420         if (properties) {
1421                 if (!wpa_dbus_get_object_properties(
1422                             iface, pgrp_obj_path,
1423                             WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter))
1424                         goto err;
1425         }
1426
1427         dbus_connection_send(iface->con, msg, NULL);
1428
1429         dbus_message_unref(msg);
1430         return;
1431
1432 err:
1433         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1434         dbus_message_unref(msg);
1435 }
1436
1437
1438 /**
1439  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
1440  *      added signal
1441  * @wpa_s: %wpa_supplicant network interface data
1442  * @id: new persistent group id
1443  *
1444  * Notify listeners about addition of a new persistent group.
1445  */
1446 static void wpas_dbus_signal_persistent_group_added(
1447         struct wpa_supplicant *wpa_s, int id)
1448 {
1449         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
1450                                           TRUE);
1451 }
1452
1453
1454 /**
1455  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
1456  *      removed signal
1457  * @wpa_s: %wpa_supplicant network interface data
1458  * @id: persistent group id
1459  *
1460  * Notify listeners about removal of a persistent group.
1461  */
1462 static void wpas_dbus_signal_persistent_group_removed(
1463         struct wpa_supplicant *wpa_s, int id)
1464 {
1465         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
1466                                           FALSE);
1467 }
1468
1469
1470 /**
1471  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
1472  * @wpa_s: %wpa_supplicant network interface data
1473  *
1474  * Sends Event dbus signal with name "fail" and dictionary containing
1475  * "msg" field with fail message number (int32) as arguments
1476  */
1477 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
1478                                      struct wps_event_fail *fail)
1479 {
1480
1481         DBusMessage *msg;
1482         DBusMessageIter iter, dict_iter;
1483         struct wpas_dbus_priv *iface;
1484         char *key = "fail";
1485
1486         iface = wpa_s->global->dbus;
1487
1488         /* Do nothing if the control interface is not turned on */
1489         if (iface == NULL)
1490                 return;
1491
1492         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1493                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1494                                       "WpsFailed");
1495         if (msg == NULL)
1496                 return;
1497
1498         dbus_message_iter_init_append(msg, &iter);
1499
1500         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
1501             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1502             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
1503             !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
1504                                         fail->config_error) ||
1505             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1506                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1507         else
1508                 dbus_connection_send(iface->con, msg, NULL);
1509
1510         dbus_message_unref(msg);
1511 }
1512
1513 #endif /*CONFIG_P2P*/
1514
1515
1516 /**
1517  * wpas_dbus_signal_prop_changed - Signals change of property
1518  * @wpa_s: %wpa_supplicant network interface data
1519  * @property: indicates which property has changed
1520  *
1521  * Sends PropertyChanged signals with path, interface and arguments
1522  * depending on which property has changed.
1523  */
1524 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
1525                                    enum wpas_dbus_prop property)
1526 {
1527         char *prop;
1528
1529         if (wpa_s->dbus_new_path == NULL)
1530                 return; /* Skip signal since D-Bus setup is not yet ready */
1531
1532         switch (property) {
1533         case WPAS_DBUS_PROP_AP_SCAN:
1534                 prop = "ApScan";
1535                 break;
1536         case WPAS_DBUS_PROP_SCANNING:
1537                 prop = "Scanning";
1538                 break;
1539         case WPAS_DBUS_PROP_STATE:
1540                 prop = "State";
1541                 break;
1542         case WPAS_DBUS_PROP_CURRENT_BSS:
1543                 prop = "CurrentBSS";
1544                 break;
1545         case WPAS_DBUS_PROP_CURRENT_NETWORK:
1546                 prop = "CurrentNetwork";
1547                 break;
1548         case WPAS_DBUS_PROP_BSSS:
1549                 prop = "BSSs";
1550                 break;
1551         case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
1552                 prop = "CurrentAuthMode";
1553                 break;
1554         default:
1555                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1556                            __func__, property);
1557                 return;
1558         }
1559
1560         wpa_dbus_mark_property_changed(wpa_s->global->dbus,
1561                                        wpa_s->dbus_new_path,
1562                                        WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
1563 }
1564
1565
1566 /**
1567  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
1568  * @wpa_s: %wpa_supplicant network interface data
1569  * @property: indicates which property has changed
1570  * @id: unique BSS identifier
1571  *
1572  * Sends PropertyChanged signals with path, interface, and arguments depending
1573  * on which property has changed.
1574  */
1575 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
1576                                        enum wpas_dbus_bss_prop property,
1577                                        unsigned int id)
1578 {
1579         char path[WPAS_DBUS_OBJECT_PATH_MAX];
1580         char *prop;
1581
1582         switch (property) {
1583         case WPAS_DBUS_BSS_PROP_SIGNAL:
1584                 prop = "Signal";
1585                 break;
1586         case WPAS_DBUS_BSS_PROP_FREQ:
1587                 prop = "Frequency";
1588                 break;
1589         case WPAS_DBUS_BSS_PROP_MODE:
1590                 prop = "Mode";
1591                 break;
1592         case WPAS_DBUS_BSS_PROP_PRIVACY:
1593                 prop = "Privacy";
1594                 break;
1595         case WPAS_DBUS_BSS_PROP_RATES:
1596                 prop = "Rates";
1597                 break;
1598         case WPAS_DBUS_BSS_PROP_WPA:
1599                 prop = "WPA";
1600                 break;
1601         case WPAS_DBUS_BSS_PROP_RSN:
1602                 prop = "RSN";
1603                 break;
1604         case WPAS_DBUS_BSS_PROP_IES:
1605                 prop = "IEs";
1606                 break;
1607         default:
1608                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1609                            __func__, property);
1610                 return;
1611         }
1612
1613         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1614                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1615                     wpa_s->dbus_new_path, id);
1616
1617         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
1618                                        WPAS_DBUS_NEW_IFACE_BSS, prop);
1619 }
1620
1621
1622 /**
1623  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
1624  * @global: wpa_global structure
1625  *
1626  * Sends PropertyChanged signals informing that debug level has changed.
1627  */
1628 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
1629 {
1630         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1631                                        WPAS_DBUS_NEW_INTERFACE,
1632                                        "DebugLevel");
1633 }
1634
1635
1636 /**
1637  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
1638  * @global: wpa_global structure
1639  *
1640  * Sends PropertyChanged signals informing that debug timestamp has changed.
1641  */
1642 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
1643 {
1644         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1645                                        WPAS_DBUS_NEW_INTERFACE,
1646                                        "DebugTimestamp");
1647 }
1648
1649
1650 /**
1651  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
1652  * @global: wpa_global structure
1653  *
1654  * Sends PropertyChanged signals informing that debug show_keys has changed.
1655  */
1656 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
1657 {
1658         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1659                                        WPAS_DBUS_NEW_INTERFACE,
1660                                        "DebugShowKeys");
1661 }
1662
1663
1664 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1665                                void *priv,
1666                                WPADBusArgumentFreeFunction priv_free,
1667                                const struct wpa_dbus_method_desc *methods,
1668                                const struct wpa_dbus_property_desc *properties,
1669                                const struct wpa_dbus_signal_desc *signals)
1670 {
1671         int n;
1672
1673         obj_desc->user_data = priv;
1674         obj_desc->user_data_free_func = priv_free;
1675         obj_desc->methods = methods;
1676         obj_desc->properties = properties;
1677         obj_desc->signals = signals;
1678
1679         for (n = 0; properties && properties->dbus_property; properties++)
1680                 n++;
1681
1682         obj_desc->prop_changed_flags = os_zalloc(n);
1683         if (!obj_desc->prop_changed_flags)
1684                 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
1685                            __func__);
1686 }
1687
1688
1689 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
1690         { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1691           (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1692           {
1693                   { "args", "a{sv}", ARG_IN },
1694                   { "path", "o", ARG_OUT },
1695                   END_ARGS
1696           }
1697         },
1698         { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1699           (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1700           {
1701                   { "path", "o", ARG_IN },
1702                   END_ARGS
1703           }
1704         },
1705         { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1706           (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1707           {
1708                   { "ifname", "s", ARG_IN },
1709                   { "path", "o", ARG_OUT },
1710                   END_ARGS
1711           }
1712         },
1713         { NULL, NULL, NULL, { END_ARGS } }
1714 };
1715
1716 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
1717         { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
1718           wpas_dbus_getter_debug_level,
1719           wpas_dbus_setter_debug_level
1720         },
1721         { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
1722           wpas_dbus_getter_debug_timestamp,
1723           wpas_dbus_setter_debug_timestamp
1724         },
1725         { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
1726           wpas_dbus_getter_debug_show_keys,
1727           wpas_dbus_setter_debug_show_keys
1728         },
1729         { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1730           wpas_dbus_getter_interfaces,
1731           NULL
1732         },
1733         { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1734           wpas_dbus_getter_eap_methods,
1735           NULL
1736         },
1737         { NULL, NULL, NULL, NULL, NULL }
1738 };
1739
1740 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
1741         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1742           {
1743                   { "path", "o", ARG_OUT },
1744                   { "properties", "a{sv}", ARG_OUT },
1745                   END_ARGS
1746           }
1747         },
1748         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1749           {
1750                   { "path", "o", ARG_OUT },
1751                   END_ARGS
1752           }
1753         },
1754         { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
1755           {
1756                   { "path", "o", ARG_OUT },
1757                   { "field", "s", ARG_OUT },
1758                   { "text", "s", ARG_OUT },
1759                   END_ARGS
1760           }
1761         },
1762         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
1763         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1764           {
1765                   { "properties", "a{sv}", ARG_OUT },
1766                   END_ARGS
1767           }
1768         },
1769         { NULL, NULL, { END_ARGS } }
1770 };
1771
1772
1773 /**
1774  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1775  * @global: Pointer to global data from wpa_supplicant_init()
1776  * Returns: 0 on success or -1 on failure
1777  *
1778  * Initialize the dbus control interface for wpa_supplicantand and start
1779  * receiving commands from external programs over the bus.
1780  */
1781 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1782 {
1783         struct wpa_dbus_object_desc *obj_desc;
1784         int ret;
1785
1786         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1787         if (!obj_desc) {
1788                 wpa_printf(MSG_ERROR, "Not enough memory "
1789                            "to create object description");
1790                 return -1;
1791         }
1792
1793         wpas_dbus_register(obj_desc, priv->global, NULL,
1794                            wpas_dbus_global_methods,
1795                            wpas_dbus_global_properties,
1796                            wpas_dbus_global_signals);
1797
1798         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1799                    WPAS_DBUS_NEW_PATH);
1800         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1801                                        WPAS_DBUS_NEW_SERVICE,
1802                                        obj_desc);
1803         if (ret < 0)
1804                 free_dbus_object_desc(obj_desc);
1805         else
1806                 priv->dbus_new_initialized = 1;
1807
1808         return ret;
1809 }
1810
1811
1812 /**
1813  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1814  * wpa_supplicant
1815  * @iface: Pointer to dbus private data from wpas_dbus_init()
1816  *
1817  * Deinitialize the dbus control interface that was initialized with
1818  * wpas_dbus_ctrl_iface_init().
1819  */
1820 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1821 {
1822         if (!iface->dbus_new_initialized)
1823                 return;
1824         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1825                    WPAS_DBUS_NEW_PATH);
1826         dbus_connection_unregister_object_path(iface->con,
1827                                                WPAS_DBUS_NEW_PATH);
1828 }
1829
1830
1831 static void wpa_dbus_free(void *ptr)
1832 {
1833         os_free(ptr);
1834 }
1835
1836
1837 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
1838         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1839           wpas_dbus_getter_network_properties,
1840           wpas_dbus_setter_network_properties
1841         },
1842         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1843           wpas_dbus_getter_enabled,
1844           wpas_dbus_setter_enabled
1845         },
1846         { NULL, NULL, NULL, NULL, NULL }
1847 };
1848
1849
1850 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
1851         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
1852         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1853           {
1854                   { "properties", "a{sv}", ARG_OUT },
1855                   END_ARGS
1856           }
1857         },
1858         { NULL, NULL, { END_ARGS } }
1859 };
1860
1861
1862 /**
1863  * wpas_dbus_register_network - Register a configured network with dbus
1864  * @wpa_s: wpa_supplicant interface structure
1865  * @ssid: network configuration data
1866  * Returns: 0 on success, -1 on failure
1867  *
1868  * Registers network representing object with dbus
1869  */
1870 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1871                                struct wpa_ssid *ssid)
1872 {
1873         struct wpas_dbus_priv *ctrl_iface;
1874         struct wpa_dbus_object_desc *obj_desc;
1875         struct network_handler_args *arg;
1876         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1877
1878 #ifdef CONFIG_P2P
1879         /*
1880          * If it is a persistent group register it as such.
1881          * This is to handle cases where an interface is being initialized
1882          * with a list of networks read from config.
1883          */
1884         if (network_is_persistent_group(ssid))
1885                 return wpas_dbus_register_persistent_group(wpa_s, ssid);
1886 #endif /* CONFIG_P2P */
1887
1888         /* Do nothing if the control interface is not turned on */
1889         if (wpa_s == NULL || wpa_s->global == NULL)
1890                 return 0;
1891         ctrl_iface = wpa_s->global->dbus;
1892         if (ctrl_iface == NULL)
1893                 return 0;
1894
1895         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1896                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1897                     wpa_s->dbus_new_path, ssid->id);
1898
1899         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1900                    net_obj_path);
1901         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1902         if (!obj_desc) {
1903                 wpa_printf(MSG_ERROR, "Not enough memory "
1904                            "to create object description");
1905                 goto err;
1906         }
1907
1908         /* allocate memory for handlers arguments */
1909         arg = os_zalloc(sizeof(struct network_handler_args));
1910         if (!arg) {
1911                 wpa_printf(MSG_ERROR, "Not enough memory "
1912                            "to create arguments for method");
1913                 goto err;
1914         }
1915
1916         arg->wpa_s = wpa_s;
1917         arg->ssid = ssid;
1918
1919         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1920                            wpas_dbus_network_properties,
1921                            wpas_dbus_network_signals);
1922
1923         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1924                                                wpa_s->ifname, obj_desc))
1925                 goto err;
1926
1927         wpas_dbus_signal_network_added(wpa_s, ssid->id);
1928
1929         return 0;
1930
1931 err:
1932         free_dbus_object_desc(obj_desc);
1933         return -1;
1934 }
1935
1936
1937 /**
1938  * wpas_dbus_unregister_network - Unregister a configured network from dbus
1939  * @wpa_s: wpa_supplicant interface structure
1940  * @nid: network id
1941  * Returns: 0 on success, -1 on failure
1942  *
1943  * Unregisters network representing object from dbus
1944  */
1945 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1946 {
1947         struct wpas_dbus_priv *ctrl_iface;
1948         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1949         int ret;
1950         struct wpa_ssid *ssid;
1951
1952         ssid = wpa_config_get_network(wpa_s->conf, nid);
1953
1954 #ifdef CONFIG_P2P
1955         /* If it is a persistent group unregister it as such */
1956         if (ssid && network_is_persistent_group(ssid))
1957                 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
1958 #endif /* CONFIG_P2P */
1959
1960         /* Do nothing if the control interface is not turned on */
1961         if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
1962                 return 0;
1963         ctrl_iface = wpa_s->global->dbus;
1964         if (ctrl_iface == NULL)
1965                 return 0;
1966
1967         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1968                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1969                     wpa_s->dbus_new_path, nid);
1970
1971         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1972                    net_obj_path);
1973         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1974
1975         if (!ret)
1976                 wpas_dbus_signal_network_removed(wpa_s, nid);
1977
1978         return ret;
1979 }
1980
1981
1982 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
1983         { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1984           wpas_dbus_getter_bss_ssid,
1985           NULL
1986         },
1987         { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1988           wpas_dbus_getter_bss_bssid,
1989           NULL
1990         },
1991         { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
1992           wpas_dbus_getter_bss_privacy,
1993           NULL
1994         },
1995         { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
1996           wpas_dbus_getter_bss_mode,
1997           NULL
1998         },
1999         { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2000           wpas_dbus_getter_bss_signal,
2001           NULL
2002         },
2003         { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2004           wpas_dbus_getter_bss_frequency,
2005           NULL
2006         },
2007         { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2008           wpas_dbus_getter_bss_rates,
2009           NULL
2010         },
2011         { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2012           wpas_dbus_getter_bss_wpa,
2013           NULL
2014         },
2015         { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2016           wpas_dbus_getter_bss_rsn,
2017           NULL
2018         },
2019         { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2020           wpas_dbus_getter_bss_ies,
2021           NULL
2022         },
2023         { NULL, NULL, NULL, NULL, NULL }
2024 };
2025
2026
2027 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2028         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2029         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2030           {
2031                   { "properties", "a{sv}", ARG_OUT },
2032                   END_ARGS
2033           }
2034         },
2035         { NULL, NULL, { END_ARGS } }
2036 };
2037
2038
2039 /**
2040  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2041  * @wpa_s: wpa_supplicant interface structure
2042  * @bssid: scanned network bssid
2043  * @id: unique BSS identifier
2044  * Returns: 0 on success, -1 on failure
2045  *
2046  * Unregisters BSS representing object from dbus
2047  */
2048 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2049                              u8 bssid[ETH_ALEN], unsigned int id)
2050 {
2051         struct wpas_dbus_priv *ctrl_iface;
2052         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2053
2054         /* Do nothing if the control interface is not turned on */
2055         if (wpa_s == NULL || wpa_s->global == NULL)
2056                 return 0;
2057         ctrl_iface = wpa_s->global->dbus;
2058         if (ctrl_iface == NULL)
2059                 return 0;
2060
2061         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2062                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2063                     wpa_s->dbus_new_path, id);
2064
2065         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2066                    bss_obj_path);
2067         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2068                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2069                            bss_obj_path);
2070                 return -1;
2071         }
2072
2073         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2074         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2075
2076         return 0;
2077 }
2078
2079
2080 /**
2081  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2082  * @wpa_s: wpa_supplicant interface structure
2083  * @bssid: scanned network bssid
2084  * @id: unique BSS identifier
2085  * Returns: 0 on success, -1 on failure
2086  *
2087  * Registers BSS representing object with dbus
2088  */
2089 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2090                            u8 bssid[ETH_ALEN], unsigned int id)
2091 {
2092         struct wpas_dbus_priv *ctrl_iface;
2093         struct wpa_dbus_object_desc *obj_desc;
2094         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2095         struct bss_handler_args *arg;
2096
2097         /* Do nothing if the control interface is not turned on */
2098         if (wpa_s == NULL || wpa_s->global == NULL)
2099                 return 0;
2100         ctrl_iface = wpa_s->global->dbus;
2101         if (ctrl_iface == NULL)
2102                 return 0;
2103
2104         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2105                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2106                     wpa_s->dbus_new_path, id);
2107
2108         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2109         if (!obj_desc) {
2110                 wpa_printf(MSG_ERROR, "Not enough memory "
2111                            "to create object description");
2112                 goto err;
2113         }
2114
2115         arg = os_zalloc(sizeof(struct bss_handler_args));
2116         if (!arg) {
2117                 wpa_printf(MSG_ERROR, "Not enough memory "
2118                            "to create arguments for handler");
2119                 goto err;
2120         }
2121         arg->wpa_s = wpa_s;
2122         arg->id = id;
2123
2124         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2125                            wpas_dbus_bss_properties,
2126                            wpas_dbus_bss_signals);
2127
2128         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2129                    bss_obj_path);
2130         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2131                                                wpa_s->ifname, obj_desc)) {
2132                 wpa_printf(MSG_ERROR,
2133                            "Cannot register BSSID dbus object %s.",
2134                            bss_obj_path);
2135                 goto err;
2136         }
2137
2138         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2139         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2140
2141         return 0;
2142
2143 err:
2144         free_dbus_object_desc(obj_desc);
2145         return -1;
2146 }
2147
2148
2149 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2150         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2151           (WPADBusMethodHandler) &wpas_dbus_handler_scan,
2152           {
2153                   { "args", "a{sv}", ARG_IN },
2154                   END_ARGS
2155           }
2156         },
2157         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2158           (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
2159           {
2160                   END_ARGS
2161           }
2162         },
2163         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2164           (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
2165           {
2166                   { "args", "a{sv}", ARG_IN },
2167                   { "path", "o", ARG_OUT },
2168                   END_ARGS
2169           }
2170         },
2171         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2172           (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
2173           {
2174                   { "path", "o", ARG_IN },
2175                   END_ARGS
2176           }
2177         },
2178         { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2179           (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
2180           {
2181                   END_ARGS
2182           }
2183         },
2184         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2185           (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
2186           {
2187                   { "path", "o", ARG_IN },
2188                   END_ARGS
2189           }
2190         },
2191         { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2192           (WPADBusMethodHandler) &wpas_dbus_handler_network_reply,
2193           {
2194                   { "path", "o", ARG_IN },
2195                   { "field", "s", ARG_IN },
2196                   { "value", "s", ARG_IN },
2197                   END_ARGS
2198           }
2199         },
2200         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2201           (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
2202           {
2203                   { "name", "s", ARG_IN },
2204                   { "data", "ay", ARG_IN },
2205                   END_ARGS
2206           }
2207         },
2208         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2209           (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
2210           {
2211                   { "name", "s", ARG_IN },
2212                   { "data", "ay", ARG_OUT },
2213                   END_ARGS
2214           }
2215         },
2216         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2217           (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
2218           {
2219                   { "name", "s", ARG_IN },
2220                   END_ARGS
2221           }
2222         },
2223 #ifdef CONFIG_WPS
2224         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
2225           (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
2226           {
2227                   { "args", "a{sv}", ARG_IN },
2228                   { "output", "a{sv}", ARG_OUT },
2229                   END_ARGS
2230           }
2231         },
2232 #endif /* CONFIG_WPS */
2233 #ifdef CONFIG_P2P
2234         { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2235           (WPADBusMethodHandler)wpas_dbus_handler_p2p_find,
2236           {
2237                   { "args", "a{sv}", ARG_IN },
2238                   END_ARGS
2239           }
2240         },
2241         { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2242           (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find,
2243           {
2244                   END_ARGS
2245           }
2246         },
2247         { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2248           (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen,
2249           {
2250                   { "timeout", "i", ARG_IN },
2251                   END_ARGS
2252           }
2253         },
2254         { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2255           (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten,
2256           {
2257                   { "args", "a{sv}", ARG_IN },
2258                   END_ARGS
2259           }
2260         },
2261         { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2262           (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request,
2263           {
2264                   { "args", "a{sv}", ARG_IN },
2265                   END_ARGS
2266           }
2267         },
2268         { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2269           (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req,
2270           {
2271                   { "peer", "o", ARG_IN },
2272                   { "config_method", "s", ARG_IN },
2273                   END_ARGS
2274           }
2275         },
2276         { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2277           (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect,
2278           {
2279                   { "args", "a{sv}", ARG_IN },
2280                   { "generated_pin", "s", ARG_OUT },
2281                   END_ARGS
2282           }
2283         },
2284         { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2285           (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add,
2286           {
2287                   { "args", "a{sv}", ARG_IN },
2288                   END_ARGS
2289           }
2290         },
2291         { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2292           (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite,
2293           {
2294                   { "args", "a{sv}", ARG_IN },
2295                   END_ARGS
2296           }
2297         },
2298         { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2299           (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect,
2300           {
2301                   END_ARGS
2302           }
2303         },
2304         { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2305           (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer,
2306           {
2307                   { "peer", "o", ARG_IN },
2308                   END_ARGS
2309           }
2310         },
2311         { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2312           (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush,
2313           {
2314                   END_ARGS
2315           }
2316         },
2317         { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2318           (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service,
2319           {
2320                   { "args", "a{sv}", ARG_IN },
2321                   END_ARGS
2322           }
2323         },
2324         { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2325           (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service,
2326           {
2327                   { "args", "a{sv}", ARG_IN },
2328                   END_ARGS
2329           }
2330         },
2331         { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2332           (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service,
2333           {
2334                   END_ARGS
2335           }
2336         },
2337         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2338           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
2339           {
2340                   { "args", "a{sv}", ARG_IN },
2341                   END_ARGS
2342           }
2343         },
2344         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2345           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res,
2346           {
2347                   { "args", "a{sv}", ARG_IN },
2348                   END_ARGS
2349           }
2350         },
2351         { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2352           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req,
2353           {
2354                   { "args", "t", ARG_IN },
2355                   END_ARGS
2356           }
2357         },
2358         { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2359           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update,
2360           {
2361                   END_ARGS
2362           }
2363         },
2364         { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2365           (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2366           {
2367                   { "arg", "i", ARG_IN },
2368                   END_ARGS
2369           }
2370         },
2371         { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2372           (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2373           {
2374                   { "arg", "i", ARG_IN },
2375                   END_ARGS
2376           }
2377         },
2378         { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2379           (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2380           {
2381                   { "args", "a{sv}", ARG_IN },
2382                   { "path", "o", ARG_OUT },
2383                   END_ARGS
2384           }
2385         },
2386         { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2387           (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
2388           {
2389                   { "path", "o", ARG_IN },
2390                   END_ARGS
2391           }
2392         },
2393         { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2394           (WPADBusMethodHandler)
2395           wpas_dbus_handler_remove_all_persistent_groups,
2396           {
2397                   END_ARGS
2398           }
2399         },
2400 #endif /* CONFIG_P2P */
2401         { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
2402           (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
2403           {
2404                   { "age", "u", ARG_IN },
2405                   END_ARGS
2406           }
2407         },
2408         { NULL, NULL, NULL, { END_ARGS } }
2409 };
2410
2411 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
2412         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
2413           wpas_dbus_getter_capabilities,
2414           NULL
2415         },
2416         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2417           wpas_dbus_getter_state,
2418           NULL
2419         },
2420         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2421           wpas_dbus_getter_scanning,
2422           NULL
2423         },
2424         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2425           wpas_dbus_getter_ap_scan,
2426           wpas_dbus_setter_ap_scan
2427         },
2428         { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2429           wpas_dbus_getter_bss_expire_age,
2430           wpas_dbus_setter_bss_expire_age
2431         },
2432         { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2433           wpas_dbus_getter_bss_expire_count,
2434           wpas_dbus_setter_bss_expire_count
2435         },
2436         { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2437           wpas_dbus_getter_country,
2438           wpas_dbus_setter_country
2439         },
2440         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2441           wpas_dbus_getter_ifname,
2442           NULL
2443         },
2444         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2445           wpas_dbus_getter_driver,
2446           NULL
2447         },
2448         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2449           wpas_dbus_getter_bridge_ifname,
2450           NULL
2451         },
2452         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2453           wpas_dbus_getter_current_bss,
2454           NULL
2455         },
2456         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2457           wpas_dbus_getter_current_network,
2458           NULL
2459         },
2460         { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2461           wpas_dbus_getter_current_auth_mode,
2462           NULL
2463         },
2464         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
2465           wpas_dbus_getter_blobs,
2466           NULL
2467         },
2468         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2469           wpas_dbus_getter_bsss,
2470           NULL
2471         },
2472         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2473           wpas_dbus_getter_networks,
2474           NULL
2475         },
2476 #ifdef CONFIG_WPS
2477         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
2478           wpas_dbus_getter_process_credentials,
2479           wpas_dbus_setter_process_credentials
2480         },
2481 #endif /* CONFIG_WPS */
2482 #ifdef CONFIG_P2P
2483         { "P2PDeviceProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
2484           wpas_dbus_getter_p2p_device_properties,
2485           wpas_dbus_setter_p2p_device_properties
2486         },
2487         { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2488           wpas_dbus_getter_p2p_peers,
2489           NULL
2490         },
2491         { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
2492           wpas_dbus_getter_p2p_role,
2493           NULL
2494         },
2495         { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2496           wpas_dbus_getter_p2p_group,
2497           NULL
2498         },
2499         { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2500           wpas_dbus_getter_p2p_peergo,
2501           NULL
2502         },
2503         { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2504           wpas_dbus_getter_persistent_groups,
2505           NULL
2506         },
2507 #endif /* CONFIG_P2P */
2508         { NULL, NULL, NULL, NULL, NULL }
2509 };
2510
2511 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
2512         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
2513           {
2514                   { "success", "b", ARG_OUT },
2515                   END_ARGS
2516           }
2517         },
2518         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2519           {
2520                   { "path", "o", ARG_OUT },
2521                   { "properties", "a{sv}", ARG_OUT },
2522                   END_ARGS
2523           }
2524         },
2525         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2526           {
2527                   { "path", "o", ARG_OUT },
2528                   END_ARGS
2529           }
2530         },
2531         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2532           {
2533                   { "name", "s", ARG_OUT },
2534                   END_ARGS
2535           }
2536         },
2537         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2538           {
2539                   { "name", "s", ARG_OUT },
2540                   END_ARGS
2541           }
2542         },
2543         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2544           {
2545                   { "path", "o", ARG_OUT },
2546                   { "properties", "a{sv}", ARG_OUT },
2547                   END_ARGS
2548           }
2549         },
2550         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2551           {
2552                   { "path", "o", ARG_OUT },
2553                   END_ARGS
2554           }
2555         },
2556         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
2557           {
2558                   { "path", "o", ARG_OUT },
2559                   END_ARGS
2560           }
2561         },
2562         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2563         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
2564           {
2565                   { "properties", "a{sv}", ARG_OUT },
2566                   END_ARGS
2567           }
2568         },
2569 #ifdef CONFIG_WPS
2570         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
2571           {
2572                   { "name", "s", ARG_OUT },
2573                   { "args", "a{sv}", ARG_OUT },
2574                   END_ARGS
2575           }
2576         },
2577         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
2578           {
2579                   { "credentials", "a{sv}", ARG_OUT },
2580                   END_ARGS
2581           }
2582         },
2583         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2584         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
2585           {
2586                   { "properties", "a{sv}", ARG_OUT },
2587                   END_ARGS
2588           }
2589         },
2590 #endif /* CONFIG_WPS */
2591 #ifdef CONFIG_P2P
2592         { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2593           {
2594                   { "states", "a{ss}", ARG_OUT },
2595                   END_ARGS
2596           }
2597         },
2598         { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2599           {
2600                   { "path", "o", ARG_OUT },
2601                   { "properties", "a{sv}", ARG_OUT },
2602                   END_ARGS
2603           }
2604         },
2605         { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2606           {
2607                   { "path", "o", ARG_OUT },
2608                   END_ARGS
2609           }
2610         },
2611         { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2612           {
2613                   { "peer_object", "o", ARG_OUT },
2614                   { "pin", "s", ARG_OUT },
2615                   END_ARGS
2616           }
2617         },
2618         { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2619           {
2620                   { "peer_object", "o", ARG_OUT },
2621                   { "pin", "s", ARG_OUT },
2622                   END_ARGS
2623           }
2624         },
2625         { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2626           {
2627                   { "peer_object", "o", ARG_OUT },
2628                   END_ARGS
2629           }
2630         },
2631         { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2632           {
2633                   { "peer_object", "o", ARG_OUT },
2634                   END_ARGS
2635           }
2636         },
2637         { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2638           {
2639                   { "peer_object", "o", ARG_OUT },
2640                   END_ARGS
2641           }
2642         },
2643         { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2644           {
2645                   { "peer_object", "o", ARG_OUT },
2646                   END_ARGS
2647           }
2648         },
2649         { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2650           {
2651                   { "peer_object", "o", ARG_OUT },
2652                   { "status", "i", ARG_OUT },
2653                   END_ARGS
2654           }
2655         },
2656         { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2657           {
2658                   { "properties", "a{sv}", ARG_OUT },
2659                   END_ARGS
2660           }
2661         },
2662         { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2663           {
2664                   END_ARGS
2665           }
2666         },
2667         { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2668           {
2669                   { "status", "i", ARG_OUT },
2670                   END_ARGS
2671           }
2672         },
2673         { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2674           {
2675                   { "path", "o", ARG_OUT },
2676                   { "dev_passwd_id", "i", ARG_OUT },
2677                   END_ARGS
2678           }
2679         },
2680         { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2681           {
2682                   { "invite_result", "a{sv}", ARG_OUT },
2683                   END_ARGS
2684           }
2685         },
2686         { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2687           {
2688                   { "ifname", "s", ARG_OUT },
2689                   { "role", "s", ARG_OUT },
2690                   END_ARGS
2691           }
2692         },
2693         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2694           {
2695                   { "sd_request", "a{sv}", ARG_OUT },
2696                   END_ARGS
2697           }
2698         },
2699         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2700           {
2701                   { "sd_response", "a{sv}", ARG_OUT },
2702                   END_ARGS
2703           }
2704         },
2705         { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2706           {
2707                   { "path", "o", ARG_OUT },
2708                   { "properties", "a{sv}", ARG_OUT },
2709                   END_ARGS
2710           }
2711         },
2712         { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2713           {
2714                   { "path", "o", ARG_OUT },
2715                   END_ARGS
2716           }
2717         },
2718         { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2719           {
2720                   { "name", "s", ARG_OUT },
2721                   { "args", "a{sv}", ARG_OUT },
2722                   END_ARGS
2723           }
2724         },
2725 #endif /* CONFIG_P2P */
2726         { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
2727           {
2728                   { "certification", "a{sv}", ARG_OUT },
2729                   END_ARGS
2730           }
2731         },
2732         { NULL, NULL, { END_ARGS } }
2733 };
2734
2735
2736 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
2737 {
2738
2739         struct wpa_dbus_object_desc *obj_desc = NULL;
2740         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
2741         int next;
2742
2743         /* Do nothing if the control interface is not turned on */
2744         if (ctrl_iface == NULL)
2745                 return 0;
2746
2747         /* Create and set the interface's object path */
2748         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2749         if (wpa_s->dbus_new_path == NULL)
2750                 return -1;
2751         next = ctrl_iface->next_objid++;
2752         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
2753                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
2754                     next);
2755
2756         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2757         if (!obj_desc) {
2758                 wpa_printf(MSG_ERROR, "Not enough memory "
2759                            "to create object description");
2760                 goto err;
2761         }
2762
2763         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
2764                            wpas_dbus_interface_properties,
2765                            wpas_dbus_interface_signals);
2766
2767         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
2768                    wpa_s->dbus_new_path);
2769         if (wpa_dbus_register_object_per_iface(ctrl_iface,
2770                                                wpa_s->dbus_new_path,
2771                                                wpa_s->ifname, obj_desc))
2772                 goto err;
2773
2774         wpas_dbus_signal_interface_added(wpa_s);
2775
2776         return 0;
2777
2778 err:
2779         os_free(wpa_s->dbus_new_path);
2780         wpa_s->dbus_new_path = NULL;
2781         free_dbus_object_desc(obj_desc);
2782         return -1;
2783 }
2784
2785
2786 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
2787 {
2788         struct wpas_dbus_priv *ctrl_iface;
2789
2790         /* Do nothing if the control interface is not turned on */
2791         if (wpa_s == NULL || wpa_s->global == NULL)
2792                 return 0;
2793         ctrl_iface = wpa_s->global->dbus;
2794         if (ctrl_iface == NULL)
2795                 return 0;
2796
2797         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
2798                    wpa_s->dbus_new_path);
2799         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
2800                                                  wpa_s->dbus_new_path))
2801                 return -1;
2802
2803         wpas_dbus_signal_interface_removed(wpa_s);
2804
2805         os_free(wpa_s->dbus_new_path);
2806         wpa_s->dbus_new_path = NULL;
2807
2808         return 0;
2809 }
2810
2811 #ifdef CONFIG_P2P
2812
2813 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
2814         { "Properties", WPAS_DBUS_NEW_IFACE_P2P_PEER, "a{sv}",
2815           wpas_dbus_getter_p2p_peer_properties,
2816           NULL
2817         },
2818         { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
2819           wpas_dbus_getter_p2p_peer_ies,
2820           NULL
2821         },
2822         { NULL, NULL, NULL, NULL, NULL }
2823 };
2824
2825 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
2826
2827         { NULL, NULL, { END_ARGS } }
2828 };
2829
2830 /**
2831  * wpas_dbus_signal_peer - Send a peer related event signal
2832  * @wpa_s: %wpa_supplicant network interface data
2833  * @dev: peer device object
2834  * @interface: name of the interface emitting this signal.
2835  *      In case of peer objects, it would be emitted by either
2836  *      the "interface object" or by "peer objects"
2837  * @sig_name: signal name - DeviceFound
2838  *
2839  * Notify listeners about event related with newly found p2p peer device
2840  */
2841 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
2842                                   const u8 *dev_addr, const char *interface,
2843                                   const char *sig_name)
2844 {
2845         struct wpas_dbus_priv *iface;
2846         DBusMessage *msg;
2847         DBusMessageIter iter;
2848         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2849
2850         iface = wpa_s->global->dbus;
2851
2852         /* Do nothing if the control interface is not turned on */
2853         if (iface == NULL)
2854                 return;
2855
2856         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2857                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2858                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
2859
2860         msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
2861                                       sig_name);
2862         if (msg == NULL)
2863                 return;
2864
2865         dbus_message_iter_init_append(msg, &iter);
2866         path = peer_obj_path;
2867         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2868                                             &path))
2869                 goto err;
2870
2871         dbus_connection_send(iface->con, msg, NULL);
2872
2873         dbus_message_unref(msg);
2874         return;
2875
2876 err:
2877         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2878         dbus_message_unref(msg);
2879 }
2880
2881
2882 /**
2883  * wpas_dbus_signal_peer_found - Send a peer found signal
2884  * @wpa_s: %wpa_supplicant network interface data
2885  * @dev: peer device object
2886  *
2887  * Notify listeners about find a p2p peer device found
2888  */
2889 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
2890                                         const u8 *dev_addr)
2891 {
2892         wpas_dbus_signal_peer(wpa_s, dev_addr,
2893                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2894                               "DeviceFound");
2895 }
2896
2897 /**
2898  * wpas_dbus_signal_peer_lost - Send a peer lost signal
2899  * @wpa_s: %wpa_supplicant network interface data
2900  * @dev: peer device object
2901  *
2902  * Notify listeners about lost a p2p peer device
2903  */
2904 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
2905                                        const u8 *dev_addr)
2906 {
2907         wpas_dbus_signal_peer(wpa_s, dev_addr,
2908                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2909                               "DeviceLost");
2910 }
2911
2912 /**
2913  * wpas_dbus_register_peer - Register a discovered peer object with dbus
2914  * @wpa_s: wpa_supplicant interface structure
2915  * @ssid: network configuration data
2916  * Returns: 0 on success, -1 on failure
2917  *
2918  * Registers network representing object with dbus
2919  */
2920 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
2921 {
2922         struct wpas_dbus_priv *ctrl_iface;
2923         struct wpa_dbus_object_desc *obj_desc;
2924         struct peer_handler_args *arg;
2925         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2926
2927         /* Do nothing if the control interface is not turned on */
2928         if (wpa_s == NULL || wpa_s->global == NULL)
2929                 return 0;
2930
2931         ctrl_iface = wpa_s->global->dbus;
2932         if (ctrl_iface == NULL)
2933                 return 0;
2934
2935         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2936                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2937                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
2938
2939         wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
2940                    peer_obj_path);
2941         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2942         if (!obj_desc) {
2943                 wpa_printf(MSG_ERROR, "Not enough memory "
2944                            "to create object description");
2945                 goto err;
2946         }
2947
2948         /* allocate memory for handlers arguments */
2949         arg = os_zalloc(sizeof(struct peer_handler_args));
2950         if (!arg) {
2951                 wpa_printf(MSG_ERROR, "Not enough memory "
2952                            "to create arguments for method");
2953                 goto err;
2954         }
2955
2956         arg->wpa_s = wpa_s;
2957         os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
2958
2959         wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
2960                            NULL,
2961                            wpas_dbus_p2p_peer_properties,
2962                            wpas_dbus_p2p_peer_signals);
2963
2964         if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
2965                                                wpa_s->ifname, obj_desc))
2966                 goto err;
2967
2968         return 0;
2969
2970 err:
2971         free_dbus_object_desc(obj_desc);
2972         return -1;
2973 }
2974
2975 /**
2976  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
2977  * @wpa_s: wpa_supplicant interface structure
2978  * @dev_addr: p2p device addr
2979  * Returns: 0 on success, -1 on failure
2980  *
2981  * Registers network representing object with dbus
2982  */
2983 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
2984                                   const u8 *dev_addr)
2985 {
2986         struct wpas_dbus_priv *ctrl_iface;
2987         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2988         int ret;
2989
2990         /* Do nothing if the control interface is not turned on */
2991         if (wpa_s == NULL || wpa_s->global == NULL ||
2992             wpa_s->dbus_new_path == NULL)
2993                 return 0;
2994         ctrl_iface = wpa_s->global->dbus;
2995         if (ctrl_iface == NULL)
2996                 return 0;
2997
2998         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2999                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3000                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3001
3002         wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
3003                    peer_obj_path);
3004         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
3005
3006         return ret;
3007 }
3008
3009
3010 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
3011         { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
3012           wpas_dbus_getter_p2p_group_members,
3013           NULL
3014         },
3015         { "Properties",
3016           WPAS_DBUS_NEW_IFACE_P2P_GROUP, "a{sv}",
3017           wpas_dbus_getter_p2p_group_properties,
3018           wpas_dbus_setter_p2p_group_properties
3019         },
3020         { NULL, NULL, NULL, NULL, NULL }
3021 };
3022
3023 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
3024         { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3025           {
3026                   { "peer", "o", ARG_OUT },
3027                   END_ARGS
3028           }
3029         },
3030         { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3031           {
3032                   { "peer", "o", ARG_OUT },
3033                   END_ARGS
3034           }
3035         },
3036         { NULL, NULL, { END_ARGS } }
3037 };
3038
3039 /**
3040  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
3041  * @wpa_s: wpa_supplicant interface structure
3042  * @ssid: SSID struct
3043  * Returns: 0 on success, -1 on failure
3044  *
3045  * Registers p2p group representing object with dbus
3046  */
3047 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
3048                                   struct wpa_ssid *ssid)
3049 {
3050         struct wpas_dbus_priv *ctrl_iface;
3051         struct wpa_dbus_object_desc *obj_desc;
3052         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3053
3054         /* Do nothing if the control interface is not turned on */
3055         if (wpa_s == NULL || wpa_s->global == NULL)
3056                 return;
3057
3058         ctrl_iface = wpa_s->global->dbus;
3059         if (ctrl_iface == NULL)
3060                 return;
3061
3062         if (wpa_s->dbus_groupobj_path) {
3063                 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
3064                            __func__, wpa_s->dbus_groupobj_path);
3065                 return;
3066         }
3067
3068         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
3069                 return;
3070
3071         wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
3072         if (wpa_s->dbus_groupobj_path == NULL)
3073                 return;
3074
3075         wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
3076                    group_obj_path);
3077         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3078         if (!obj_desc) {
3079                 wpa_printf(MSG_ERROR, "Not enough memory "
3080                            "to create object description");
3081                 goto err;
3082         }
3083
3084         wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
3085                            wpas_dbus_p2p_group_properties,
3086                            wpas_dbus_p2p_group_signals);
3087
3088         if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3089                                                wpa_s->ifname, obj_desc))
3090                 goto err;
3091
3092         return;
3093
3094 err:
3095         if (wpa_s->dbus_groupobj_path) {
3096                 os_free(wpa_s->dbus_groupobj_path);
3097                 wpa_s->dbus_groupobj_path = NULL;
3098         }
3099
3100         free_dbus_object_desc(obj_desc);
3101 }
3102
3103 /**
3104  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3105  * @wpa_s: wpa_supplicant interface structure
3106  * @ssid: network name of the p2p group started
3107  */
3108 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3109                                     const struct wpa_ssid *ssid)
3110 {
3111         struct wpas_dbus_priv *ctrl_iface;
3112
3113         /* Do nothing if the control interface is not turned on */
3114         if (wpa_s == NULL || wpa_s->global == NULL)
3115                 return;
3116
3117         ctrl_iface = wpa_s->global->dbus;
3118         if (ctrl_iface == NULL)
3119                 return;
3120
3121         if (!wpa_s->dbus_groupobj_path) {
3122                 wpa_printf(MSG_DEBUG,
3123                            "%s: Group object '%s' already unregistered",
3124                            __func__, wpa_s->dbus_groupobj_path);
3125                 return;
3126         }
3127
3128         wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3129                    wpa_s->dbus_groupobj_path);
3130
3131         wpa_dbus_unregister_object_per_iface(ctrl_iface,
3132                                              wpa_s->dbus_groupobj_path);
3133
3134         os_free(wpa_s->dbus_groupobj_path);
3135         wpa_s->dbus_groupobj_path = NULL;
3136 }
3137
3138 static const struct wpa_dbus_property_desc
3139 wpas_dbus_p2p_groupmember_properties[] = {
3140         { "Properties", WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER, "a{sv}",
3141           wpas_dbus_getter_p2p_group_properties,
3142           NULL
3143         },
3144         { NULL, NULL, NULL, NULL, NULL }
3145 };
3146
3147 /**
3148  * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
3149  * object with dbus
3150  * @wpa_s: wpa_supplicant interface structure
3151  * @p2p_if_addr: i/f addr of the device joining this group
3152  *
3153  * Registers p2p groupmember representing object with dbus
3154  */
3155 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
3156                                         const u8 *p2p_if_addr)
3157 {
3158         struct wpas_dbus_priv *ctrl_iface;
3159         struct wpa_dbus_object_desc *obj_desc = NULL;
3160         struct groupmember_handler_args *arg;
3161         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3162
3163         /* Do nothing if the control interface is not turned on */
3164         if (wpa_s == NULL || wpa_s->global == NULL)
3165                 return;
3166
3167         ctrl_iface = wpa_s->global->dbus;
3168         if (ctrl_iface == NULL)
3169                 return;
3170
3171         if (!wpa_s->dbus_groupobj_path)
3172                 return;
3173
3174         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3175                 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3176                 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3177
3178         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3179         if (!obj_desc) {
3180                 wpa_printf(MSG_ERROR, "Not enough memory "
3181                            "to create object description");
3182                 goto err;
3183         }
3184
3185         /* allocate memory for handlers arguments */
3186         arg = os_zalloc(sizeof(struct groupmember_handler_args));
3187         if (!arg) {
3188                 wpa_printf(MSG_ERROR, "Not enough memory "
3189                            "to create arguments for method");
3190                 goto err;
3191         }
3192
3193         arg->wpa_s = wpa_s;
3194         os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
3195
3196         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3197                            wpas_dbus_p2p_groupmember_properties, NULL);
3198
3199         if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
3200                                                wpa_s->ifname, obj_desc))
3201                 goto err;
3202
3203         wpa_printf(MSG_INFO,
3204                    "dbus: Registered group member object '%s' successfully",
3205                    groupmember_obj_path);
3206         return;
3207
3208 err:
3209         free_dbus_object_desc(obj_desc);
3210 }
3211
3212 /**
3213  * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
3214  * object with dbus
3215  * @wpa_s: wpa_supplicant interface structure
3216  * @p2p_if_addr: i/f addr of the device joining this group
3217  *
3218  * Unregisters p2p groupmember representing object with dbus
3219  */
3220 void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
3221                                           const u8 *p2p_if_addr)
3222 {
3223         struct wpas_dbus_priv *ctrl_iface;
3224         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3225
3226         /* Do nothing if the control interface is not turned on */
3227         if (wpa_s == NULL || wpa_s->global == NULL)
3228                 return;
3229
3230         ctrl_iface = wpa_s->global->dbus;
3231         if (ctrl_iface == NULL)
3232                 return;
3233
3234         if (!wpa_s->dbus_groupobj_path)
3235                 return;
3236
3237         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3238                 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3239                 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3240
3241         wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
3242 }
3243
3244
3245 static const struct wpa_dbus_property_desc
3246         wpas_dbus_persistent_group_properties[] = {
3247         { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3248           wpas_dbus_getter_persistent_group_properties,
3249           wpas_dbus_setter_persistent_group_properties
3250         },
3251         { NULL, NULL, NULL, NULL, NULL }
3252 };
3253
3254 /* No signals intended for persistent group objects */
3255
3256 /**
3257  * wpas_dbus_register_persistent_group - Register a configured(saved)
3258  *      persistent group with dbus
3259  * @wpa_s: wpa_supplicant interface structure
3260  * @ssid: persistent group (still represented as a network within wpa)
3261  *        configuration data
3262  * Returns: 0 on success, -1 on failure
3263  *
3264  * Registers a persistent group representing object with dbus.
3265  */
3266 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3267                                         struct wpa_ssid *ssid)
3268 {
3269         struct wpas_dbus_priv *ctrl_iface;
3270         struct wpa_dbus_object_desc *obj_desc;
3271         struct network_handler_args *arg;
3272         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3273
3274         /* Do nothing if the control interface is not turned on */
3275         if (wpa_s == NULL || wpa_s->global == NULL)
3276                 return 0;
3277
3278         /* Make sure ssid is a persistent group */
3279         if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3280                 return -1; /* should we return w/o complaining? */
3281
3282         ctrl_iface = wpa_s->global->dbus;
3283         if (ctrl_iface == NULL)
3284                 return 0;
3285
3286         /*
3287          * Intentionally not coming up with different numbering scheme
3288          * for persistent groups.
3289          */
3290         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3291                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3292                     wpa_s->dbus_new_path, ssid->id);
3293
3294         wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3295                    pgrp_obj_path);
3296         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3297         if (!obj_desc) {
3298                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3299                            "object description");
3300                 goto err;
3301         }
3302
3303         /*
3304          * Reusing the same context structure as that for networks
3305          * since these are represented using same data structure.
3306          */
3307         /* allocate memory for handlers arguments */
3308         arg = os_zalloc(sizeof(struct network_handler_args));
3309         if (!arg) {
3310                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3311                            "arguments for method");
3312                 goto err;
3313         }
3314
3315         arg->wpa_s = wpa_s;
3316         arg->ssid = ssid;
3317
3318         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3319                            wpas_dbus_persistent_group_properties,
3320                            NULL);
3321
3322         if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3323                                                wpa_s->ifname, obj_desc))
3324                 goto err;
3325
3326         wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3327
3328         return 0;
3329
3330 err:
3331         free_dbus_object_desc(obj_desc);
3332         return -1;
3333 }
3334
3335
3336 /**
3337  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3338  *      from dbus
3339  * @wpa_s: wpa_supplicant interface structure
3340  * @nid: network id
3341  * Returns: 0 on success, -1 on failure
3342  *
3343  * Unregisters persistent group representing object from dbus
3344  *
3345  * NOTE: There is a slight issue with the semantics here. While the
3346  * implementation simply means the persistent group is unloaded from memory,
3347  * it should not get interpreted as the group is actually being erased/removed
3348  * from persistent storage as well.
3349  */
3350 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3351                                           int nid)
3352 {
3353         struct wpas_dbus_priv *ctrl_iface;
3354         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3355         int ret;
3356
3357         /* Do nothing if the control interface is not turned on */
3358         if (wpa_s == NULL || wpa_s->global == NULL ||
3359             wpa_s->dbus_new_path == NULL)
3360                 return 0;
3361         ctrl_iface = wpa_s->global->dbus;
3362         if (ctrl_iface == NULL)
3363                 return 0;
3364
3365         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3366                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3367                     wpa_s->dbus_new_path, nid);
3368
3369         wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3370                    pgrp_obj_path);
3371         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3372
3373         if (!ret)
3374                 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3375
3376         return ret;
3377 }
3378
3379 #endif /* CONFIG_P2P */