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