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