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