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