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