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