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