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