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