D-Bus: Coding style cleanup
[mech_eap.git] / wpa_supplicant / dbus / dbus_new.c
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "wps/wps.h"
16 #include "../config.h"
17 #include "../wpa_supplicant_i.h"
18 #include "../bss.h"
19 #include "../wpas_glue.h"
20 #include "dbus_new_helpers.h"
21 #include "dbus_dict_helpers.h"
22 #include "dbus_new.h"
23 #include "dbus_new_handlers.h"
24 #include "dbus_common_i.h"
25 #include "dbus_new_handlers_p2p.h"
26 #include "p2p/p2p.h"
27 #include "../p2p_supplicant.h"
28
29 #ifdef CONFIG_AP /* until needed by something else */
30
31 /*
32  * NameOwnerChanged handling
33  *
34  * Some services we provide allow an application to register for
35  * a signal that it needs. While it can also unregister, we must
36  * be prepared for the case where the application simply crashes
37  * and thus doesn't clean up properly. The way to handle this in
38  * DBus is to register for the NameOwnerChanged signal which will
39  * signal an owner change to NULL if the peer closes the socket
40  * for whatever reason.
41  *
42  * Handle this signal via a filter function whenever necessary.
43  * The code below also handles refcounting in case in the future
44  * there will be multiple instances of this subscription scheme.
45  */
46 static const char wpas_dbus_noc_filter_str[] =
47         "interface=org.freedesktop.DBus,member=NameOwnerChanged";
48
49
50 static DBusHandlerResult noc_filter(DBusConnection *conn,
51                                     DBusMessage *message, void *data)
52 {
53         struct wpas_dbus_priv *priv = data;
54
55         if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
56                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
57
58         if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
59                                    "NameOwnerChanged")) {
60                 const char *name;
61                 const char *prev_owner;
62                 const char *new_owner;
63                 DBusError derr;
64                 struct wpa_supplicant *wpa_s;
65
66                 dbus_error_init(&derr);
67
68                 if (!dbus_message_get_args(message, &derr,
69                                            DBUS_TYPE_STRING, &name,
70                                            DBUS_TYPE_STRING, &prev_owner,
71                                            DBUS_TYPE_STRING, &new_owner,
72                                            DBUS_TYPE_INVALID)) {
73                         /* Ignore this error */
74                         dbus_error_free(&derr);
75                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
76                 }
77
78                 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
79                         if (wpa_s->preq_notify_peer != NULL &&
80                             os_strcmp(name, wpa_s->preq_notify_peer) == 0 &&
81                             (new_owner == NULL || os_strlen(new_owner) == 0)) {
82                                 /* probe request owner disconnected */
83                                 os_free(wpa_s->preq_notify_peer);
84                                 wpa_s->preq_notify_peer = NULL;
85                                 wpas_dbus_unsubscribe_noc(priv);
86                         }
87                 }
88         }
89
90         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
91 }
92
93
94 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv)
95 {
96         priv->dbus_noc_refcnt++;
97         if (priv->dbus_noc_refcnt > 1)
98                 return;
99
100         if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) {
101                 wpa_printf(MSG_ERROR, "dbus: failed to add filter");
102                 return;
103         }
104
105         dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL);
106 }
107
108
109 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
110 {
111         priv->dbus_noc_refcnt--;
112         if (priv->dbus_noc_refcnt > 0)
113                 return;
114
115         dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL);
116         dbus_connection_remove_filter(priv->con, noc_filter, priv);
117 }
118
119 #endif /* CONFIG_AP */
120
121
122 /**
123  * wpas_dbus_signal_interface - Send a interface related event signal
124  * @wpa_s: %wpa_supplicant network interface data
125  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
126  * @properties: Whether to add second argument with object properties
127  *
128  * Notify listeners about event related with interface
129  */
130 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
131                                        const char *sig_name, int properties)
132 {
133         struct wpas_dbus_priv *iface;
134         DBusMessage *msg;
135         DBusMessageIter iter;
136
137         iface = wpa_s->global->dbus;
138
139         /* Do nothing if the control interface is not turned on */
140         if (iface == NULL)
141                 return;
142
143         msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
144                                       WPAS_DBUS_NEW_INTERFACE, sig_name);
145         if (msg == NULL)
146                 return;
147
148         dbus_message_iter_init_append(msg, &iter);
149         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
150                                             &wpa_s->dbus_new_path) ||
151             (properties &&
152              !wpa_dbus_get_object_properties(
153                      iface, wpa_s->dbus_new_path,
154                      WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)))
155                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
156         else
157                 dbus_connection_send(iface->con, msg, NULL);
158         dbus_message_unref(msg);
159 }
160
161
162 /**
163  * wpas_dbus_signal_interface_added - Send a interface created signal
164  * @wpa_s: %wpa_supplicant network interface data
165  *
166  * Notify listeners about creating new interface
167  */
168 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
169 {
170         wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
171 }
172
173
174 /**
175  * wpas_dbus_signal_interface_removed - Send a interface removed signal
176  * @wpa_s: %wpa_supplicant network interface data
177  *
178  * Notify listeners about removing interface
179  */
180 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
181 {
182         wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
183
184 }
185
186
187 /**
188  * wpas_dbus_signal_scan_done - send scan done signal
189  * @wpa_s: %wpa_supplicant network interface data
190  * @success: indicates if scanning succeed or failed
191  *
192  * Notify listeners about finishing a scan
193  */
194 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
195 {
196         struct wpas_dbus_priv *iface;
197         DBusMessage *msg;
198         dbus_bool_t succ;
199
200         iface = wpa_s->global->dbus;
201
202         /* Do nothing if the control interface is not turned on */
203         if (iface == NULL)
204                 return;
205
206         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
207                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
208                                       "ScanDone");
209         if (msg == NULL)
210                 return;
211
212         succ = success ? TRUE : FALSE;
213         if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
214                                      DBUS_TYPE_INVALID))
215                 dbus_connection_send(iface->con, msg, NULL);
216         else
217                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
218         dbus_message_unref(msg);
219 }
220
221
222 /**
223  * wpas_dbus_signal_bss - Send a BSS related event signal
224  * @wpa_s: %wpa_supplicant network interface data
225  * @bss_obj_path: BSS object path
226  * @sig_name: signal name - BSSAdded or BSSRemoved
227  * @properties: Whether to add second argument with object properties
228  *
229  * Notify listeners about event related with BSS
230  */
231 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
232                                  const char *bss_obj_path,
233                                  const char *sig_name, int properties)
234 {
235         struct wpas_dbus_priv *iface;
236         DBusMessage *msg;
237         DBusMessageIter iter;
238
239         iface = wpa_s->global->dbus;
240
241         /* Do nothing if the control interface is not turned on */
242         if (iface == NULL)
243                 return;
244
245         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
246                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
247                                       sig_name);
248         if (msg == NULL)
249                 return;
250
251         dbus_message_iter_init_append(msg, &iter);
252         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
253                                             &bss_obj_path) ||
254             (properties &&
255              !wpa_dbus_get_object_properties(iface, bss_obj_path,
256                                              WPAS_DBUS_NEW_IFACE_BSS,
257                                              &iter)))
258                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
259         else
260                 dbus_connection_send(iface->con, msg, NULL);
261         dbus_message_unref(msg);
262 }
263
264
265 /**
266  * wpas_dbus_signal_bss_added - Send a BSS added signal
267  * @wpa_s: %wpa_supplicant network interface data
268  * @bss_obj_path: new BSS object path
269  *
270  * Notify listeners about adding new BSS
271  */
272 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
273                                        const char *bss_obj_path)
274 {
275         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
276 }
277
278
279 /**
280  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
281  * @wpa_s: %wpa_supplicant network interface data
282  * @bss_obj_path: BSS object path
283  *
284  * Notify listeners about removing BSS
285  */
286 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
287                                          const char *bss_obj_path)
288 {
289         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
290 }
291
292
293 /**
294  * wpas_dbus_signal_blob - Send a blob related event signal
295  * @wpa_s: %wpa_supplicant network interface data
296  * @name: blob name
297  * @sig_name: signal name - BlobAdded or BlobRemoved
298  *
299  * Notify listeners about event related with blob
300  */
301 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
302                                   const char *name, const char *sig_name)
303 {
304         struct wpas_dbus_priv *iface;
305         DBusMessage *msg;
306
307         iface = wpa_s->global->dbus;
308
309         /* Do nothing if the control interface is not turned on */
310         if (iface == NULL)
311                 return;
312
313         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
314                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
315                                       sig_name);
316         if (msg == NULL)
317                 return;
318
319         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
320                                      DBUS_TYPE_INVALID))
321                 dbus_connection_send(iface->con, msg, NULL);
322         else
323                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
324         dbus_message_unref(msg);
325 }
326
327
328 /**
329  * wpas_dbus_signal_blob_added - Send a blob added signal
330  * @wpa_s: %wpa_supplicant network interface data
331  * @name: blob name
332  *
333  * Notify listeners about adding a new blob
334  */
335 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
336                                  const char *name)
337 {
338         wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
339 }
340
341
342 /**
343  * wpas_dbus_signal_blob_removed - Send a blob removed signal
344  * @wpa_s: %wpa_supplicant network interface data
345  * @name: blob name
346  *
347  * Notify listeners about removing blob
348  */
349 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
350                                    const char *name)
351 {
352         wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
353 }
354
355
356 /**
357  * wpas_dbus_signal_network - Send a network related event signal
358  * @wpa_s: %wpa_supplicant network interface data
359  * @id: new network id
360  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
361  * @properties: determines if add second argument with object properties
362  *
363  * Notify listeners about event related with configured network
364  */
365 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
366                                      int id, const char *sig_name,
367                                      int properties)
368 {
369         struct wpas_dbus_priv *iface;
370         DBusMessage *msg;
371         DBusMessageIter iter;
372         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
373
374         iface = wpa_s->global->dbus;
375
376         /* Do nothing if the control interface is not turned on */
377         if (iface == NULL)
378                 return;
379
380         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
381                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
382                     wpa_s->dbus_new_path, id);
383
384         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
385                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
386                                       sig_name);
387         if (msg == NULL)
388                 return;
389
390         dbus_message_iter_init_append(msg, &iter);
391         path = net_obj_path;
392         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
393                                             &path) ||
394             (properties &&
395              !wpa_dbus_get_object_properties(
396                      iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
397                      &iter)))
398                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
399         else
400                 dbus_connection_send(iface->con, msg, NULL);
401         dbus_message_unref(msg);
402 }
403
404
405 /**
406  * wpas_dbus_signal_network_added - Send a network added signal
407  * @wpa_s: %wpa_supplicant network interface data
408  * @id: new network id
409  *
410  * Notify listeners about adding new network
411  */
412 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
413                                            int id)
414 {
415         wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
416 }
417
418
419 /**
420  * wpas_dbus_signal_network_removed - Send a network removed signal
421  * @wpa_s: %wpa_supplicant network interface data
422  * @id: network id
423  *
424  * Notify listeners about removing a network
425  */
426 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
427                                              int id)
428 {
429         wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
430 }
431
432
433 /**
434  * wpas_dbus_signal_network_selected - Send a network selected signal
435  * @wpa_s: %wpa_supplicant network interface data
436  * @id: network id
437  *
438  * Notify listeners about selecting a network
439  */
440 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
441 {
442         wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
443 }
444
445
446 /**
447  * wpas_dbus_signal_network_request - Indicate that additional information
448  * (EAP password, etc.) is required to complete the association to this SSID
449  * @wpa_s: %wpa_supplicant network interface data
450  * @rtype: The specific additional information required
451  * @default_text: Optional description of required information
452  *
453  * Request additional information or passwords to complete an association
454  * request.
455  */
456 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
457                                       struct wpa_ssid *ssid,
458                                       enum wpa_ctrl_req_type rtype,
459                                       const char *default_txt)
460 {
461         struct wpas_dbus_priv *iface;
462         DBusMessage *msg;
463         DBusMessageIter iter;
464         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
465         const char *field, *txt = NULL, *net_ptr;
466
467         iface = wpa_s->global->dbus;
468
469         /* Do nothing if the control interface is not turned on */
470         if (iface == NULL)
471                 return;
472
473         field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
474         if (field == NULL)
475                 return;
476
477         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
478                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
479                                       "NetworkRequest");
480         if (msg == NULL)
481                 return;
482
483         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
484                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
485                     wpa_s->dbus_new_path, ssid->id);
486         net_ptr = &net_obj_path[0];
487
488         dbus_message_iter_init_append(msg, &iter);
489         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
490                                             &net_ptr) ||
491             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) ||
492             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
493                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
494         else
495                 dbus_connection_send(iface->con, msg, NULL);
496         dbus_message_unref(msg);
497 }
498
499
500 /**
501  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
502  * @wpa_s: %wpa_supplicant network interface data
503  * @ssid: configured network which Enabled property has changed
504  *
505  * Sends PropertyChanged signals containing new value of Enabled property
506  * for specified network
507  */
508 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
509                                               struct wpa_ssid *ssid)
510 {
511
512         char path[WPAS_DBUS_OBJECT_PATH_MAX];
513
514         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
1541         iface = wpa_s->global->dbus;
1542
1543         /* Do nothing if the control interface is not turned on */
1544         if (iface == NULL)
1545                 return;
1546
1547         if (wpa_s->p2p_mgmt)
1548                 wpa_s = wpa_s->parent;
1549
1550         /* Check if this is a known peer */
1551         if (!p2p_peer_known(wpa_s->global->p2p, sa))
1552                 return;
1553
1554         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1555                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1556                                       "ServiceDiscoveryRequest");
1557         if (msg == NULL)
1558                 return;
1559
1560         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1561                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1562                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1563
1564         path = peer_obj_path;
1565
1566         dbus_message_iter_init_append(msg, &iter);
1567         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1568             !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1569                                               path) ||
1570             !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1571             !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1572                                         dialog_token) ||
1573             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1574                                          update_indic) ||
1575             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1576                                              (const char *) tlvs,
1577                                              tlvs_len) ||
1578             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1579                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1580         else
1581                 dbus_connection_send(iface->con, msg, NULL);
1582         dbus_message_unref(msg);
1583 }
1584
1585
1586 /**
1587  *
1588  * Method to emit a signal for a service discovery response.
1589  * The signal will carry station address, update indicator and it
1590  * tlvs
1591  *
1592  * @wpa_s: %wpa_supplicant network interface data
1593  * @sa: station addr (p2p i/f) of the peer
1594  * @update_indic: service discovery request update indicator
1595  * @tlvs: service discovery request genrated byte array of tlvs
1596  * @tlvs_len: service discovery request tlvs length
1597  */
1598 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1599                                       const u8 *sa, u16 update_indic,
1600                                       const u8 *tlvs, size_t tlvs_len)
1601 {
1602         DBusMessage *msg;
1603         DBusMessageIter iter, dict_iter;
1604         struct wpas_dbus_priv *iface;
1605         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1606
1607         iface = wpa_s->global->dbus;
1608
1609         /* Do nothing if the control interface is not turned on */
1610         if (iface == NULL)
1611                 return;
1612
1613         if (wpa_s->p2p_mgmt)
1614                 wpa_s = wpa_s->parent;
1615
1616         /* Check if this is a known peer */
1617         if (!p2p_peer_known(wpa_s->global->p2p, sa))
1618                 return;
1619
1620         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1621                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1622                                       "ServiceDiscoveryResponse");
1623         if (msg == NULL)
1624                 return;
1625
1626         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1627                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1628                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1629
1630         path = peer_obj_path;
1631
1632         dbus_message_iter_init_append(msg, &iter);
1633         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1634             !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1635                                               path) ||
1636             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1637                                          update_indic) ||
1638             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1639                                              (const char *) tlvs,
1640                                              tlvs_len) ||
1641             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1642                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1643         else
1644                 dbus_connection_send(iface->con, msg, NULL);
1645         dbus_message_unref(msg);
1646 }
1647
1648
1649 /**
1650  * wpas_dbus_signal_persistent_group - Send a persistent group related
1651  *      event signal
1652  * @wpa_s: %wpa_supplicant network interface data
1653  * @id: new persistent group id
1654  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1655  * @properties: determines if add second argument with object properties
1656  *
1657  * Notify listeners about an event related to persistent groups.
1658  */
1659 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1660                                               int id, const char *sig_name,
1661                                               int properties)
1662 {
1663         struct wpas_dbus_priv *iface;
1664         DBusMessage *msg;
1665         DBusMessageIter iter;
1666         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1667
1668         iface = wpa_s->global->dbus;
1669
1670         /* Do nothing if the control interface is not turned on */
1671         if (iface == NULL)
1672                 return;
1673
1674         if (wpa_s->p2p_mgmt)
1675                 wpa_s = wpa_s->parent;
1676
1677         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1678                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1679                     wpa_s->dbus_new_path, id);
1680
1681         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1682                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1683                                       sig_name);
1684         if (msg == NULL)
1685                 return;
1686
1687         dbus_message_iter_init_append(msg, &iter);
1688         path = pgrp_obj_path;
1689         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1690                                             &path) ||
1691             (properties &&
1692              !wpa_dbus_get_object_properties(
1693                      iface, pgrp_obj_path,
1694                      WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
1695                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1696         else
1697                 dbus_connection_send(iface->con, msg, NULL);
1698
1699         dbus_message_unref(msg);
1700 }
1701
1702
1703 /**
1704  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
1705  *      added signal
1706  * @wpa_s: %wpa_supplicant network interface data
1707  * @id: new persistent group id
1708  *
1709  * Notify listeners about addition of a new persistent group.
1710  */
1711 static void wpas_dbus_signal_persistent_group_added(
1712         struct wpa_supplicant *wpa_s, int id)
1713 {
1714         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
1715                                           TRUE);
1716 }
1717
1718
1719 /**
1720  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
1721  *      removed signal
1722  * @wpa_s: %wpa_supplicant network interface data
1723  * @id: persistent group id
1724  *
1725  * Notify listeners about removal of a persistent group.
1726  */
1727 static void wpas_dbus_signal_persistent_group_removed(
1728         struct wpa_supplicant *wpa_s, int id)
1729 {
1730         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
1731                                           FALSE);
1732 }
1733
1734
1735 /**
1736  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
1737  * @wpa_s: %wpa_supplicant network interface data
1738  *
1739  * Sends Event dbus signal with name "fail" and dictionary containing
1740  * "msg" field with fail message number (int32) as arguments
1741  */
1742 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
1743                                      struct wps_event_fail *fail)
1744 {
1745
1746         DBusMessage *msg;
1747         DBusMessageIter iter, dict_iter;
1748         struct wpas_dbus_priv *iface;
1749         char *key = "fail";
1750
1751         iface = wpa_s->global->dbus;
1752
1753         /* Do nothing if the control interface is not turned on */
1754         if (iface == NULL)
1755                 return;
1756
1757         if (wpa_s->p2p_mgmt)
1758                 wpa_s = wpa_s->parent;
1759
1760         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1761                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1762                                       "WpsFailed");
1763         if (msg == NULL)
1764                 return;
1765
1766         dbus_message_iter_init_append(msg, &iter);
1767
1768         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
1769             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1770             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
1771             !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
1772                                         fail->config_error) ||
1773             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1774                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1775         else
1776                 dbus_connection_send(iface->con, msg, NULL);
1777
1778         dbus_message_unref(msg);
1779 }
1780
1781 #endif /* CONFIG_P2P */
1782
1783
1784 /**
1785  * wpas_dbus_signal_prop_changed - Signals change of property
1786  * @wpa_s: %wpa_supplicant network interface data
1787  * @property: indicates which property has changed
1788  *
1789  * Sends PropertyChanged signals with path, interface and arguments
1790  * depending on which property has changed.
1791  */
1792 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
1793                                    enum wpas_dbus_prop property)
1794 {
1795         char *prop;
1796         dbus_bool_t flush;
1797
1798         if (wpa_s->dbus_new_path == NULL)
1799                 return; /* Skip signal since D-Bus setup is not yet ready */
1800
1801         flush = FALSE;
1802         switch (property) {
1803         case WPAS_DBUS_PROP_AP_SCAN:
1804                 prop = "ApScan";
1805                 break;
1806         case WPAS_DBUS_PROP_SCANNING:
1807                 prop = "Scanning";
1808                 break;
1809         case WPAS_DBUS_PROP_STATE:
1810                 prop = "State";
1811                 break;
1812         case WPAS_DBUS_PROP_CURRENT_BSS:
1813                 prop = "CurrentBSS";
1814                 break;
1815         case WPAS_DBUS_PROP_CURRENT_NETWORK:
1816                 prop = "CurrentNetwork";
1817                 break;
1818         case WPAS_DBUS_PROP_BSSS:
1819                 prop = "BSSs";
1820                 break;
1821         case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
1822                 prop = "CurrentAuthMode";
1823                 break;
1824         case WPAS_DBUS_PROP_DISCONNECT_REASON:
1825                 prop = "DisconnectReason";
1826                 flush = TRUE;
1827                 break;
1828         default:
1829                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1830                            __func__, property);
1831                 return;
1832         }
1833
1834         wpa_dbus_mark_property_changed(wpa_s->global->dbus,
1835                                        wpa_s->dbus_new_path,
1836                                        WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
1837         if (flush) {
1838                 wpa_dbus_flush_object_changed_properties(
1839                         wpa_s->global->dbus->con, wpa_s->dbus_new_path);
1840         }
1841 }
1842
1843
1844 /**
1845  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
1846  * @wpa_s: %wpa_supplicant network interface data
1847  * @property: indicates which property has changed
1848  * @id: unique BSS identifier
1849  *
1850  * Sends PropertyChanged signals with path, interface, and arguments depending
1851  * on which property has changed.
1852  */
1853 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
1854                                        enum wpas_dbus_bss_prop property,
1855                                        unsigned int id)
1856 {
1857         char path[WPAS_DBUS_OBJECT_PATH_MAX];
1858         char *prop;
1859
1860         switch (property) {
1861         case WPAS_DBUS_BSS_PROP_SIGNAL:
1862                 prop = "Signal";
1863                 break;
1864         case WPAS_DBUS_BSS_PROP_FREQ:
1865                 prop = "Frequency";
1866                 break;
1867         case WPAS_DBUS_BSS_PROP_MODE:
1868                 prop = "Mode";
1869                 break;
1870         case WPAS_DBUS_BSS_PROP_PRIVACY:
1871                 prop = "Privacy";
1872                 break;
1873         case WPAS_DBUS_BSS_PROP_RATES:
1874                 prop = "Rates";
1875                 break;
1876         case WPAS_DBUS_BSS_PROP_WPA:
1877                 prop = "WPA";
1878                 break;
1879         case WPAS_DBUS_BSS_PROP_RSN:
1880                 prop = "RSN";
1881                 break;
1882         case WPAS_DBUS_BSS_PROP_WPS:
1883                 prop = "WPS";
1884                 break;
1885         case WPAS_DBUS_BSS_PROP_IES:
1886                 prop = "IEs";
1887                 break;
1888         case WPAS_DBUS_BSS_PROP_AGE:
1889                 prop = "Age";
1890                 break;
1891         default:
1892                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1893                            __func__, property);
1894                 return;
1895         }
1896
1897         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1898                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1899                     wpa_s->dbus_new_path, id);
1900
1901         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
1902                                        WPAS_DBUS_NEW_IFACE_BSS, prop);
1903 }
1904
1905
1906 /**
1907  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
1908  * @global: wpa_global structure
1909  *
1910  * Sends PropertyChanged signals informing that debug level has changed.
1911  */
1912 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
1913 {
1914         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1915                                        WPAS_DBUS_NEW_INTERFACE,
1916                                        "DebugLevel");
1917 }
1918
1919
1920 /**
1921  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
1922  * @global: wpa_global structure
1923  *
1924  * Sends PropertyChanged signals informing that debug timestamp has changed.
1925  */
1926 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
1927 {
1928         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1929                                        WPAS_DBUS_NEW_INTERFACE,
1930                                        "DebugTimestamp");
1931 }
1932
1933
1934 /**
1935  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
1936  * @global: wpa_global structure
1937  *
1938  * Sends PropertyChanged signals informing that debug show_keys has changed.
1939  */
1940 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
1941 {
1942         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1943                                        WPAS_DBUS_NEW_INTERFACE,
1944                                        "DebugShowKeys");
1945 }
1946
1947
1948 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1949                                void *priv,
1950                                WPADBusArgumentFreeFunction priv_free,
1951                                const struct wpa_dbus_method_desc *methods,
1952                                const struct wpa_dbus_property_desc *properties,
1953                                const struct wpa_dbus_signal_desc *signals)
1954 {
1955         int n;
1956
1957         obj_desc->user_data = priv;
1958         obj_desc->user_data_free_func = priv_free;
1959         obj_desc->methods = methods;
1960         obj_desc->properties = properties;
1961         obj_desc->signals = signals;
1962
1963         for (n = 0; properties && properties->dbus_property; properties++)
1964                 n++;
1965
1966         obj_desc->prop_changed_flags = os_zalloc(n);
1967         if (!obj_desc->prop_changed_flags)
1968                 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
1969                            __func__);
1970 }
1971
1972
1973 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
1974         { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1975           (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
1976           {
1977                   { "args", "a{sv}", ARG_IN },
1978                   { "path", "o", ARG_OUT },
1979                   END_ARGS
1980           }
1981         },
1982         { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1983           (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
1984           {
1985                   { "path", "o", ARG_IN },
1986                   END_ARGS
1987           }
1988         },
1989         { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1990           (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
1991           {
1992                   { "ifname", "s", ARG_IN },
1993                   { "path", "o", ARG_OUT },
1994                   END_ARGS
1995           }
1996         },
1997         { NULL, NULL, NULL, { END_ARGS } }
1998 };
1999
2000 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2001         { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2002           wpas_dbus_getter_debug_level,
2003           wpas_dbus_setter_debug_level
2004         },
2005         { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2006           wpas_dbus_getter_debug_timestamp,
2007           wpas_dbus_setter_debug_timestamp
2008         },
2009         { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2010           wpas_dbus_getter_debug_show_keys,
2011           wpas_dbus_setter_debug_show_keys
2012         },
2013         { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2014           wpas_dbus_getter_interfaces,
2015           NULL
2016         },
2017         { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2018           wpas_dbus_getter_eap_methods,
2019           NULL
2020         },
2021         { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2022           wpas_dbus_getter_global_capabilities,
2023           NULL
2024         },
2025 #ifdef CONFIG_WIFI_DISPLAY
2026         { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2027           wpas_dbus_getter_global_wfd_ies,
2028           wpas_dbus_setter_global_wfd_ies
2029         },
2030 #endif /* CONFIG_WIFI_DISPLAY */
2031         { NULL, NULL, NULL, NULL, NULL }
2032 };
2033
2034 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2035         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2036           {
2037                   { "path", "o", ARG_OUT },
2038                   { "properties", "a{sv}", ARG_OUT },
2039                   END_ARGS
2040           }
2041         },
2042         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2043           {
2044                   { "path", "o", ARG_OUT },
2045                   END_ARGS
2046           }
2047         },
2048         { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
2049           {
2050                   { "path", "o", ARG_OUT },
2051                   { "field", "s", ARG_OUT },
2052                   { "text", "s", ARG_OUT },
2053                   END_ARGS
2054           }
2055         },
2056         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2057         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2058           {
2059                   { "properties", "a{sv}", ARG_OUT },
2060                   END_ARGS
2061           }
2062         },
2063         { NULL, NULL, { END_ARGS } }
2064 };
2065
2066
2067 /**
2068  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2069  * @global: Pointer to global data from wpa_supplicant_init()
2070  * Returns: 0 on success or -1 on failure
2071  *
2072  * Initialize the dbus control interface for wpa_supplicantand and start
2073  * receiving commands from external programs over the bus.
2074  */
2075 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2076 {
2077         struct wpa_dbus_object_desc *obj_desc;
2078         int ret;
2079
2080         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2081         if (!obj_desc) {
2082                 wpa_printf(MSG_ERROR,
2083                            "Not enough memory to create object description");
2084                 return -1;
2085         }
2086
2087         wpas_dbus_register(obj_desc, priv->global, NULL,
2088                            wpas_dbus_global_methods,
2089                            wpas_dbus_global_properties,
2090                            wpas_dbus_global_signals);
2091
2092         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2093                    WPAS_DBUS_NEW_PATH);
2094         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2095                                        WPAS_DBUS_NEW_SERVICE,
2096                                        obj_desc);
2097         if (ret < 0)
2098                 free_dbus_object_desc(obj_desc);
2099         else
2100                 priv->dbus_new_initialized = 1;
2101
2102         return ret;
2103 }
2104
2105
2106 /**
2107  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2108  * wpa_supplicant
2109  * @iface: Pointer to dbus private data from wpas_dbus_init()
2110  *
2111  * Deinitialize the dbus control interface that was initialized with
2112  * wpas_dbus_ctrl_iface_init().
2113  */
2114 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
2115 {
2116         if (!iface->dbus_new_initialized)
2117                 return;
2118         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2119                    WPAS_DBUS_NEW_PATH);
2120         dbus_connection_unregister_object_path(iface->con,
2121                                                WPAS_DBUS_NEW_PATH);
2122 }
2123
2124
2125 static void wpa_dbus_free(void *ptr)
2126 {
2127         os_free(ptr);
2128 }
2129
2130
2131 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2132         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2133           wpas_dbus_getter_network_properties,
2134           wpas_dbus_setter_network_properties
2135         },
2136         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2137           wpas_dbus_getter_enabled,
2138           wpas_dbus_setter_enabled
2139         },
2140         { NULL, NULL, NULL, NULL, NULL }
2141 };
2142
2143
2144 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2145         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2146         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2147           {
2148                   { "properties", "a{sv}", ARG_OUT },
2149                   END_ARGS
2150           }
2151         },
2152         { NULL, NULL, { END_ARGS } }
2153 };
2154
2155
2156 /**
2157  * wpas_dbus_register_network - Register a configured network with dbus
2158  * @wpa_s: wpa_supplicant interface structure
2159  * @ssid: network configuration data
2160  * Returns: 0 on success, -1 on failure
2161  *
2162  * Registers network representing object with dbus
2163  */
2164 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2165                                struct wpa_ssid *ssid)
2166 {
2167         struct wpas_dbus_priv *ctrl_iface;
2168         struct wpa_dbus_object_desc *obj_desc;
2169         struct network_handler_args *arg;
2170         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2171
2172 #ifdef CONFIG_P2P
2173         /*
2174          * If it is a persistent group register it as such.
2175          * This is to handle cases where an interface is being initialized
2176          * with a list of networks read from config.
2177          */
2178         if (network_is_persistent_group(ssid))
2179                 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2180 #endif /* CONFIG_P2P */
2181
2182         /* Do nothing if the control interface is not turned on */
2183         if (wpa_s == NULL || wpa_s->global == NULL)
2184                 return 0;
2185         ctrl_iface = wpa_s->global->dbus;
2186         if (ctrl_iface == NULL)
2187                 return 0;
2188
2189         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2190                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2191                     wpa_s->dbus_new_path, ssid->id);
2192
2193         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2194                    net_obj_path);
2195         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2196         if (!obj_desc) {
2197                 wpa_printf(MSG_ERROR,
2198                            "Not enough memory to create object description");
2199                 goto err;
2200         }
2201
2202         /* allocate memory for handlers arguments */
2203         arg = os_zalloc(sizeof(struct network_handler_args));
2204         if (!arg) {
2205                 wpa_printf(MSG_ERROR,
2206                            "Not enough memory to create arguments for method");
2207                 goto err;
2208         }
2209
2210         arg->wpa_s = wpa_s;
2211         arg->ssid = ssid;
2212
2213         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2214                            wpas_dbus_network_properties,
2215                            wpas_dbus_network_signals);
2216
2217         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2218                                                wpa_s->ifname, obj_desc))
2219                 goto err;
2220
2221         wpas_dbus_signal_network_added(wpa_s, ssid->id);
2222
2223         return 0;
2224
2225 err:
2226         free_dbus_object_desc(obj_desc);
2227         return -1;
2228 }
2229
2230
2231 /**
2232  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2233  * @wpa_s: wpa_supplicant interface structure
2234  * @nid: network id
2235  * Returns: 0 on success, -1 on failure
2236  *
2237  * Unregisters network representing object from dbus
2238  */
2239 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2240 {
2241         struct wpas_dbus_priv *ctrl_iface;
2242         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2243         int ret;
2244 #ifdef CONFIG_P2P
2245         struct wpa_ssid *ssid;
2246
2247         ssid = wpa_config_get_network(wpa_s->conf, nid);
2248
2249         /* If it is a persistent group unregister it as such */
2250         if (ssid && network_is_persistent_group(ssid))
2251                 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2252 #endif /* CONFIG_P2P */
2253
2254         /* Do nothing if the control interface is not turned on */
2255         if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2256                 return 0;
2257         ctrl_iface = wpa_s->global->dbus;
2258         if (ctrl_iface == NULL)
2259                 return 0;
2260
2261         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2262                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2263                     wpa_s->dbus_new_path, nid);
2264
2265         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2266                    net_obj_path);
2267         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2268
2269         if (!ret)
2270                 wpas_dbus_signal_network_removed(wpa_s, nid);
2271
2272         return ret;
2273 }
2274
2275
2276 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2277         { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2278           wpas_dbus_getter_bss_ssid,
2279           NULL
2280         },
2281         { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2282           wpas_dbus_getter_bss_bssid,
2283           NULL
2284         },
2285         { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2286           wpas_dbus_getter_bss_privacy,
2287           NULL
2288         },
2289         { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2290           wpas_dbus_getter_bss_mode,
2291           NULL
2292         },
2293         { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2294           wpas_dbus_getter_bss_signal,
2295           NULL
2296         },
2297         { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2298           wpas_dbus_getter_bss_frequency,
2299           NULL
2300         },
2301         { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2302           wpas_dbus_getter_bss_rates,
2303           NULL
2304         },
2305         { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2306           wpas_dbus_getter_bss_wpa,
2307           NULL
2308         },
2309         { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2310           wpas_dbus_getter_bss_rsn,
2311           NULL
2312         },
2313         { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2314           wpas_dbus_getter_bss_wps,
2315           NULL
2316         },
2317         { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2318           wpas_dbus_getter_bss_ies,
2319           NULL
2320         },
2321         { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2322           wpas_dbus_getter_bss_age,
2323           NULL
2324         },
2325         { NULL, NULL, NULL, NULL, NULL }
2326 };
2327
2328
2329 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2330         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2331         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2332           {
2333                   { "properties", "a{sv}", ARG_OUT },
2334                   END_ARGS
2335           }
2336         },
2337         { NULL, NULL, { END_ARGS } }
2338 };
2339
2340
2341 /**
2342  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2343  * @wpa_s: wpa_supplicant interface structure
2344  * @bssid: scanned network bssid
2345  * @id: unique BSS identifier
2346  * Returns: 0 on success, -1 on failure
2347  *
2348  * Unregisters BSS representing object from dbus
2349  */
2350 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2351                              u8 bssid[ETH_ALEN], unsigned int id)
2352 {
2353         struct wpas_dbus_priv *ctrl_iface;
2354         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2355
2356         /* Do nothing if the control interface is not turned on */
2357         if (wpa_s == NULL || wpa_s->global == NULL)
2358                 return 0;
2359         ctrl_iface = wpa_s->global->dbus;
2360         if (ctrl_iface == NULL)
2361                 return 0;
2362
2363         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2364                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2365                     wpa_s->dbus_new_path, id);
2366
2367         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2368                    bss_obj_path);
2369         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2370                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2371                            bss_obj_path);
2372                 return -1;
2373         }
2374
2375         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2376         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2377
2378         return 0;
2379 }
2380
2381
2382 /**
2383  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2384  * @wpa_s: wpa_supplicant interface structure
2385  * @bssid: scanned network bssid
2386  * @id: unique BSS identifier
2387  * Returns: 0 on success, -1 on failure
2388  *
2389  * Registers BSS representing object with dbus
2390  */
2391 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2392                            u8 bssid[ETH_ALEN], unsigned int id)
2393 {
2394         struct wpas_dbus_priv *ctrl_iface;
2395         struct wpa_dbus_object_desc *obj_desc;
2396         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2397         struct bss_handler_args *arg;
2398
2399         /* Do nothing if the control interface is not turned on */
2400         if (wpa_s == NULL || wpa_s->global == NULL)
2401                 return 0;
2402         ctrl_iface = wpa_s->global->dbus;
2403         if (ctrl_iface == NULL)
2404                 return 0;
2405
2406         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2407                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2408                     wpa_s->dbus_new_path, id);
2409
2410         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2411         if (!obj_desc) {
2412                 wpa_printf(MSG_ERROR,
2413                            "Not enough memory to create object description");
2414                 goto err;
2415         }
2416
2417         arg = os_zalloc(sizeof(struct bss_handler_args));
2418         if (!arg) {
2419                 wpa_printf(MSG_ERROR,
2420                            "Not enough memory to create arguments for handler");
2421                 goto err;
2422         }
2423         arg->wpa_s = wpa_s;
2424         arg->id = id;
2425
2426         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2427                            wpas_dbus_bss_properties,
2428                            wpas_dbus_bss_signals);
2429
2430         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2431                    bss_obj_path);
2432         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2433                                                wpa_s->ifname, obj_desc)) {
2434                 wpa_printf(MSG_ERROR,
2435                            "Cannot register BSSID dbus object %s.",
2436                            bss_obj_path);
2437                 goto err;
2438         }
2439
2440         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2441         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2442
2443         return 0;
2444
2445 err:
2446         free_dbus_object_desc(obj_desc);
2447         return -1;
2448 }
2449
2450
2451 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2452         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2453           (WPADBusMethodHandler) wpas_dbus_handler_scan,
2454           {
2455                   { "args", "a{sv}", ARG_IN },
2456                   END_ARGS
2457           }
2458         },
2459         { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
2460           (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
2461           {
2462                   { "args", "a{sv}", ARG_OUT },
2463                   END_ARGS
2464           }
2465         },
2466         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2467           (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
2468           {
2469                   END_ARGS
2470           }
2471         },
2472         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2473           (WPADBusMethodHandler) wpas_dbus_handler_add_network,
2474           {
2475                   { "args", "a{sv}", ARG_IN },
2476                   { "path", "o", ARG_OUT },
2477                   END_ARGS
2478           }
2479         },
2480         { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
2481           (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
2482           {
2483                   END_ARGS
2484           }
2485         },
2486         { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
2487           (WPADBusMethodHandler) wpas_dbus_handler_reattach,
2488           {
2489                   END_ARGS
2490           }
2491         },
2492         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2493           (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
2494           {
2495                   { "path", "o", ARG_IN },
2496                   END_ARGS
2497           }
2498         },
2499         { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2500           (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
2501           {
2502                   END_ARGS
2503           }
2504         },
2505         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2506           (WPADBusMethodHandler) wpas_dbus_handler_select_network,
2507           {
2508                   { "path", "o", ARG_IN },
2509                   END_ARGS
2510           }
2511         },
2512         { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2513           (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
2514           {
2515                   { "path", "o", ARG_IN },
2516                   { "field", "s", ARG_IN },
2517                   { "value", "s", ARG_IN },
2518                   END_ARGS
2519           }
2520         },
2521 #ifndef CONFIG_NO_CONFIG_BLOBS
2522         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2523           (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
2524           {
2525                   { "name", "s", ARG_IN },
2526                   { "data", "ay", ARG_IN },
2527                   END_ARGS
2528           }
2529         },
2530         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2531           (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
2532           {
2533                   { "name", "s", ARG_IN },
2534                   { "data", "ay", ARG_OUT },
2535                   END_ARGS
2536           }
2537         },
2538         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2539           (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
2540           {
2541                   { "name", "s", ARG_IN },
2542                   END_ARGS
2543           }
2544         },
2545 #endif /* CONFIG_NO_CONFIG_BLOBS */
2546         { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
2547           (WPADBusMethodHandler)
2548           wpas_dbus_handler_set_pkcs11_engine_and_module_path,
2549           {
2550                   { "pkcs11_engine_path", "s", ARG_IN },
2551                   { "pkcs11_module_path", "s", ARG_IN },
2552                   END_ARGS
2553           }
2554         },
2555 #ifdef CONFIG_WPS
2556         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
2557           (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
2558           {
2559                   { "args", "a{sv}", ARG_IN },
2560                   { "output", "a{sv}", ARG_OUT },
2561                   END_ARGS
2562           }
2563         },
2564 #endif /* CONFIG_WPS */
2565 #ifdef CONFIG_P2P
2566         { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2567           (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
2568           {
2569                   { "args", "a{sv}", ARG_IN },
2570                   END_ARGS
2571           }
2572         },
2573         { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2574           (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
2575           {
2576                   END_ARGS
2577           }
2578         },
2579         { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2580           (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
2581           {
2582                   { "timeout", "i", ARG_IN },
2583                   END_ARGS
2584           }
2585         },
2586         { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2587           (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
2588           {
2589                   { "args", "a{sv}", ARG_IN },
2590                   END_ARGS
2591           }
2592         },
2593         { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2594           (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
2595           {
2596                   { "args", "a{sv}", ARG_IN },
2597                   END_ARGS
2598           }
2599         },
2600         { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2601           (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
2602           {
2603                   { "peer", "o", ARG_IN },
2604                   { "config_method", "s", ARG_IN },
2605                   END_ARGS
2606           }
2607         },
2608         { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2609           (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
2610           {
2611                   { "args", "a{sv}", ARG_IN },
2612                   { "generated_pin", "s", ARG_OUT },
2613                   END_ARGS
2614           }
2615         },
2616         { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2617           (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
2618           {
2619                   { "args", "a{sv}", ARG_IN },
2620                   END_ARGS
2621           }
2622         },
2623         { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2624           (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
2625           {
2626                   { "args", "a{sv}", ARG_IN },
2627                   END_ARGS
2628           }
2629         },
2630         { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2631           (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
2632           {
2633                   END_ARGS
2634           }
2635         },
2636         { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2637           (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
2638           {
2639                   { "peer", "o", ARG_IN },
2640                   END_ARGS
2641           }
2642         },
2643         { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2644           (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
2645           {
2646                   END_ARGS
2647           }
2648         },
2649         { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2650           (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
2651           {
2652                   { "args", "a{sv}", ARG_IN },
2653                   END_ARGS
2654           }
2655         },
2656         { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2657           (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
2658           {
2659                   { "args", "a{sv}", ARG_IN },
2660                   END_ARGS
2661           }
2662         },
2663         { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2664           (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
2665           {
2666                   END_ARGS
2667           }
2668         },
2669         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2670           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
2671           {
2672                   { "args", "a{sv}", ARG_IN },
2673                   { "ref", "t", ARG_OUT },
2674                   END_ARGS
2675           }
2676         },
2677         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2678           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
2679           {
2680                   { "args", "a{sv}", ARG_IN },
2681                   END_ARGS
2682           }
2683         },
2684         { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2685           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
2686           {
2687                   { "args", "t", ARG_IN },
2688                   END_ARGS
2689           }
2690         },
2691         { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2692           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
2693           {
2694                   END_ARGS
2695           }
2696         },
2697         { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2698           (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
2699           {
2700                   { "arg", "i", ARG_IN },
2701                   END_ARGS
2702           }
2703         },
2704         { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2705           (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2706           {
2707                   { "args", "a{sv}", ARG_IN },
2708                   { "path", "o", ARG_OUT },
2709                   END_ARGS
2710           }
2711         },
2712         { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2713           (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
2714           {
2715                   { "path", "o", ARG_IN },
2716                   END_ARGS
2717           }
2718         },
2719         { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2720           (WPADBusMethodHandler)
2721           wpas_dbus_handler_remove_all_persistent_groups,
2722           {
2723                   END_ARGS
2724           }
2725         },
2726 #endif /* CONFIG_P2P */
2727         { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
2728           (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
2729           {
2730                   { "age", "u", ARG_IN },
2731                   END_ARGS
2732           }
2733         },
2734 #ifdef CONFIG_AP
2735         { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2736           (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
2737           {
2738                   END_ARGS
2739           }
2740         },
2741         { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2742           (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
2743           {
2744                   END_ARGS
2745           }
2746         },
2747 #endif /* CONFIG_AP */
2748         { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
2749           (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
2750           {
2751                   END_ARGS
2752           }
2753         },
2754         { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
2755           (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
2756           {
2757                   END_ARGS
2758           }
2759         },
2760 #ifdef CONFIG_AUTOSCAN
2761         { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2762           (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
2763           {
2764                   { "arg", "s", ARG_IN },
2765                   END_ARGS
2766           }
2767         },
2768 #endif /* CONFIG_AUTOSCAN */
2769 #ifdef CONFIG_TDLS
2770         { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
2771           (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
2772           {
2773                   { "peer_address", "s", ARG_IN },
2774                   END_ARGS
2775           }
2776         },
2777         { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
2778           (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
2779           {
2780                   { "peer_address", "s", ARG_IN },
2781                   END_ARGS
2782           }
2783         },
2784         { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
2785           (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
2786           {
2787                   { "peer_address", "s", ARG_IN },
2788                   { "status", "s", ARG_OUT },
2789                   END_ARGS
2790           }
2791         },
2792         { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
2793           (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
2794           {
2795                   { "peer_address", "s", ARG_IN },
2796                   END_ARGS
2797           }
2798         },
2799 #endif /* CONFIG_TDLS */
2800         { NULL, NULL, NULL, { END_ARGS } }
2801 };
2802
2803 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
2804         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
2805           wpas_dbus_getter_capabilities,
2806           NULL
2807         },
2808         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2809           wpas_dbus_getter_state,
2810           NULL
2811         },
2812         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2813           wpas_dbus_getter_scanning,
2814           NULL
2815         },
2816         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2817           wpas_dbus_getter_ap_scan,
2818           wpas_dbus_setter_ap_scan
2819         },
2820         { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2821           wpas_dbus_getter_bss_expire_age,
2822           wpas_dbus_setter_bss_expire_age
2823         },
2824         { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2825           wpas_dbus_getter_bss_expire_count,
2826           wpas_dbus_setter_bss_expire_count
2827         },
2828         { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2829           wpas_dbus_getter_country,
2830           wpas_dbus_setter_country
2831         },
2832         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2833           wpas_dbus_getter_ifname,
2834           NULL
2835         },
2836         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2837           wpas_dbus_getter_driver,
2838           NULL
2839         },
2840         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2841           wpas_dbus_getter_bridge_ifname,
2842           NULL
2843         },
2844         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2845           wpas_dbus_getter_current_bss,
2846           NULL
2847         },
2848         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2849           wpas_dbus_getter_current_network,
2850           NULL
2851         },
2852         { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2853           wpas_dbus_getter_current_auth_mode,
2854           NULL
2855         },
2856         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
2857           wpas_dbus_getter_blobs,
2858           NULL
2859         },
2860         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2861           wpas_dbus_getter_bsss,
2862           NULL
2863         },
2864         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2865           wpas_dbus_getter_networks,
2866           NULL
2867         },
2868         { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2869           wpas_dbus_getter_fast_reauth,
2870           wpas_dbus_setter_fast_reauth
2871         },
2872         { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2873           wpas_dbus_getter_scan_interval,
2874           wpas_dbus_setter_scan_interval
2875         },
2876         { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2877           wpas_dbus_getter_pkcs11_engine_path,
2878           NULL
2879         },
2880         { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2881           wpas_dbus_getter_pkcs11_module_path,
2882           NULL
2883         },
2884 #ifdef CONFIG_WPS
2885         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
2886           wpas_dbus_getter_process_credentials,
2887           wpas_dbus_setter_process_credentials
2888         },
2889         { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
2890           wpas_dbus_getter_config_methods,
2891           wpas_dbus_setter_config_methods
2892         },
2893 #endif /* CONFIG_WPS */
2894 #ifdef CONFIG_P2P
2895         { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
2896           wpas_dbus_getter_p2p_device_config,
2897           wpas_dbus_setter_p2p_device_config
2898         },
2899         { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2900           wpas_dbus_getter_p2p_peers,
2901           NULL
2902         },
2903         { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
2904           wpas_dbus_getter_p2p_role,
2905           NULL
2906         },
2907         { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2908           wpas_dbus_getter_p2p_group,
2909           NULL
2910         },
2911         { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2912           wpas_dbus_getter_p2p_peergo,
2913           NULL
2914         },
2915         { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2916           wpas_dbus_getter_persistent_groups,
2917           NULL
2918         },
2919 #endif /* CONFIG_P2P */
2920         { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2921           wpas_dbus_getter_disconnect_reason,
2922           NULL
2923         },
2924         { NULL, NULL, NULL, NULL, NULL }
2925 };
2926
2927 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
2928         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
2929           {
2930                   { "success", "b", ARG_OUT },
2931                   END_ARGS
2932           }
2933         },
2934         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2935           {
2936                   { "path", "o", ARG_OUT },
2937                   { "properties", "a{sv}", ARG_OUT },
2938                   END_ARGS
2939           }
2940         },
2941         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2942           {
2943                   { "path", "o", ARG_OUT },
2944                   END_ARGS
2945           }
2946         },
2947         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2948           {
2949                   { "name", "s", ARG_OUT },
2950                   END_ARGS
2951           }
2952         },
2953         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2954           {
2955                   { "name", "s", ARG_OUT },
2956                   END_ARGS
2957           }
2958         },
2959         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2960           {
2961                   { "path", "o", ARG_OUT },
2962                   { "properties", "a{sv}", ARG_OUT },
2963                   END_ARGS
2964           }
2965         },
2966         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2967           {
2968                   { "path", "o", ARG_OUT },
2969                   END_ARGS
2970           }
2971         },
2972         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
2973           {
2974                   { "path", "o", ARG_OUT },
2975                   END_ARGS
2976           }
2977         },
2978         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2979         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
2980           {
2981                   { "properties", "a{sv}", ARG_OUT },
2982                   END_ARGS
2983           }
2984         },
2985 #ifdef CONFIG_WPS
2986         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
2987           {
2988                   { "name", "s", ARG_OUT },
2989                   { "args", "a{sv}", ARG_OUT },
2990                   END_ARGS
2991           }
2992         },
2993         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
2994           {
2995                   { "credentials", "a{sv}", ARG_OUT },
2996                   END_ARGS
2997           }
2998         },
2999         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3000         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
3001           {
3002                   { "properties", "a{sv}", ARG_OUT },
3003                   END_ARGS
3004           }
3005         },
3006 #endif /* CONFIG_WPS */
3007 #ifdef CONFIG_P2P
3008         { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3009           {
3010                   { "states", "a{ss}", ARG_OUT },
3011                   END_ARGS
3012           }
3013         },
3014         { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3015           {
3016                   { "path", "o", ARG_OUT },
3017                   END_ARGS
3018           }
3019         },
3020         { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3021           {
3022                   { "path", "o", ARG_OUT },
3023                   END_ARGS
3024           }
3025         },
3026         { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3027           {
3028                   { "peer_object", "o", ARG_OUT },
3029                   { "pin", "s", ARG_OUT },
3030                   END_ARGS
3031           }
3032         },
3033         { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3034           {
3035                   { "peer_object", "o", ARG_OUT },
3036                   { "pin", "s", ARG_OUT },
3037                   END_ARGS
3038           }
3039         },
3040         { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3041           {
3042                   { "peer_object", "o", ARG_OUT },
3043                   END_ARGS
3044           }
3045         },
3046         { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3047           {
3048                   { "peer_object", "o", ARG_OUT },
3049                   END_ARGS
3050           }
3051         },
3052         { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3053           {
3054                   { "peer_object", "o", ARG_OUT },
3055                   END_ARGS
3056           }
3057         },
3058         { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3059           {
3060                   { "peer_object", "o", ARG_OUT },
3061                   END_ARGS
3062           }
3063         },
3064         { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3065           {
3066                   { "peer_object", "o", ARG_OUT },
3067                   { "status", "i", ARG_OUT },
3068                   END_ARGS
3069           }
3070         },
3071         { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3072           {
3073                   { "properties", "a{sv}", ARG_OUT },
3074                   END_ARGS
3075           }
3076         },
3077         { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3078           {
3079                   { "properties", "a{sv}", ARG_OUT },
3080                   END_ARGS
3081           }
3082         },
3083         { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3084           {
3085                   { "properties", "a{sv}", ARG_OUT },
3086                   END_ARGS
3087           }
3088         },
3089         { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3090           {
3091                   { "path", "o", ARG_OUT },
3092                   { "dev_passwd_id", "i", ARG_OUT },
3093                   END_ARGS
3094           }
3095         },
3096         { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3097           {
3098                   { "invite_result", "a{sv}", ARG_OUT },
3099                   END_ARGS
3100           }
3101         },
3102         { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3103           {
3104                   { "properties", "a{sv}", ARG_OUT },
3105                   END_ARGS
3106           }
3107         },
3108         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3109           {
3110                   { "sd_request", "a{sv}", ARG_OUT },
3111                   END_ARGS
3112           }
3113         },
3114         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3115           {
3116                   { "sd_response", "a{sv}", ARG_OUT },
3117                   END_ARGS
3118           }
3119         },
3120         { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3121           {
3122                   { "path", "o", ARG_OUT },
3123                   { "properties", "a{sv}", ARG_OUT },
3124                   END_ARGS
3125           }
3126         },
3127         { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3128           {
3129                   { "path", "o", ARG_OUT },
3130                   END_ARGS
3131           }
3132         },
3133         { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3134           {
3135                   { "name", "s", ARG_OUT },
3136                   { "args", "a{sv}", ARG_OUT },
3137                   END_ARGS
3138           }
3139         },
3140 #endif /* CONFIG_P2P */
3141 #ifdef CONFIG_AP
3142         { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
3143           {
3144                   { "args", "a{sv}", ARG_OUT },
3145                   END_ARGS
3146           }
3147         },
3148 #endif /* CONFIG_AP */
3149         { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
3150           {
3151                   { "certification", "a{sv}", ARG_OUT },
3152                   END_ARGS
3153           }
3154         },
3155         { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
3156           {
3157                   { "status", "s", ARG_OUT },
3158                   { "parameter", "s", ARG_OUT },
3159                   END_ARGS
3160           }
3161         },
3162         { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3163           {
3164                   { "name", "s", ARG_OUT },
3165                   END_ARGS
3166           }
3167         },
3168         { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3169           {
3170                   { "name", "s", ARG_OUT },
3171                   END_ARGS
3172           }
3173         },
3174         { NULL, NULL, { END_ARGS } }
3175 };
3176
3177
3178 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
3179 {
3180
3181         struct wpa_dbus_object_desc *obj_desc = NULL;
3182         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
3183         int next;
3184
3185         /* Do nothing if the control interface is not turned on */
3186         if (ctrl_iface == NULL)
3187                 return 0;
3188
3189         /* Create and set the interface's object path */
3190         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3191         if (wpa_s->dbus_new_path == NULL)
3192                 return -1;
3193         next = ctrl_iface->next_objid++;
3194         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
3195                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
3196                     next);
3197
3198         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3199         if (!obj_desc) {
3200                 wpa_printf(MSG_ERROR,
3201                            "Not enough memory to create object description");
3202                 goto err;
3203         }
3204
3205         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
3206                            wpas_dbus_interface_properties,
3207                            wpas_dbus_interface_signals);
3208
3209         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
3210                    wpa_s->dbus_new_path);
3211         if (wpa_dbus_register_object_per_iface(ctrl_iface,
3212                                                wpa_s->dbus_new_path,
3213                                                wpa_s->ifname, obj_desc))
3214                 goto err;
3215
3216         wpas_dbus_signal_interface_added(wpa_s);
3217
3218         return 0;
3219
3220 err:
3221         os_free(wpa_s->dbus_new_path);
3222         wpa_s->dbus_new_path = NULL;
3223         free_dbus_object_desc(obj_desc);
3224         return -1;
3225 }
3226
3227
3228 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
3229 {
3230         struct wpas_dbus_priv *ctrl_iface;
3231
3232         /* Do nothing if the control interface is not turned on */
3233         if (wpa_s == NULL || wpa_s->global == NULL)
3234                 return 0;
3235         ctrl_iface = wpa_s->global->dbus;
3236         if (ctrl_iface == NULL)
3237                 return 0;
3238
3239         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
3240                    wpa_s->dbus_new_path);
3241
3242 #ifdef CONFIG_AP
3243         if (wpa_s->preq_notify_peer) {
3244                 wpas_dbus_unsubscribe_noc(ctrl_iface);
3245                 os_free(wpa_s->preq_notify_peer);
3246                 wpa_s->preq_notify_peer = NULL;
3247         }
3248 #endif /* CONFIG_AP */
3249
3250         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3251                                                  wpa_s->dbus_new_path))
3252                 return -1;
3253
3254         wpas_dbus_signal_interface_removed(wpa_s);
3255
3256         os_free(wpa_s->dbus_new_path);
3257         wpa_s->dbus_new_path = NULL;
3258
3259         return 0;
3260 }
3261
3262 #ifdef CONFIG_P2P
3263
3264 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
3265         { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3266           wpas_dbus_getter_p2p_peer_device_name,
3267           NULL
3268         },
3269         { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3270           wpas_dbus_getter_p2p_peer_primary_device_type,
3271           NULL
3272         },
3273         { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
3274           wpas_dbus_getter_p2p_peer_config_method,
3275           NULL
3276         },
3277         { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
3278           wpas_dbus_getter_p2p_peer_level,
3279           NULL
3280         },
3281         { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3282           wpas_dbus_getter_p2p_peer_device_capability,
3283           NULL
3284         },
3285         { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3286           wpas_dbus_getter_p2p_peer_group_capability,
3287           NULL
3288         },
3289         { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3290           wpas_dbus_getter_p2p_peer_secondary_device_types,
3291           NULL
3292         },
3293         { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3294           wpas_dbus_getter_p2p_peer_vendor_extension,
3295           NULL
3296         },
3297         { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3298           wpas_dbus_getter_p2p_peer_ies,
3299           NULL
3300         },
3301         { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3302           wpas_dbus_getter_p2p_peer_device_address,
3303           NULL
3304         },
3305         { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
3306           wpas_dbus_getter_p2p_peer_groups,
3307           NULL
3308         },
3309         { NULL, NULL, NULL, NULL, NULL }
3310 };
3311
3312 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
3313         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3314         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
3315           {
3316                   { "properties", "a{sv}", ARG_OUT },
3317                   END_ARGS
3318           }
3319         },
3320         { NULL, NULL, { END_ARGS } }
3321 };
3322
3323 /**
3324  * wpas_dbus_signal_peer - Send a peer related event signal
3325  * @wpa_s: %wpa_supplicant network interface data
3326  * @dev: peer device object
3327  * @interface: name of the interface emitting this signal.
3328  *      In case of peer objects, it would be emitted by either
3329  *      the "interface object" or by "peer objects"
3330  * @sig_name: signal name - DeviceFound
3331  *
3332  * Notify listeners about event related with newly found p2p peer device
3333  */
3334 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
3335                                   const u8 *dev_addr, const char *interface,
3336                                   const char *sig_name)
3337 {
3338         struct wpas_dbus_priv *iface;
3339         DBusMessage *msg;
3340         DBusMessageIter iter;
3341         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
3342
3343         if (wpa_s->p2p_mgmt)
3344                 wpa_s = wpa_s->parent;
3345
3346         iface = wpa_s->global->dbus;
3347
3348         /* Do nothing if the control interface is not turned on */
3349         if (iface == NULL)
3350                 return;
3351
3352         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3353                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3354                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3355
3356         msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
3357                                       sig_name);
3358         if (msg == NULL)
3359                 return;
3360
3361         dbus_message_iter_init_append(msg, &iter);
3362         path = peer_obj_path;
3363         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
3364                                             &path))
3365                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3366         else
3367                 dbus_connection_send(iface->con, msg, NULL);
3368
3369         dbus_message_unref(msg);
3370 }
3371
3372
3373 /**
3374  * wpas_dbus_signal_peer_found - Send a peer found signal
3375  * @wpa_s: %wpa_supplicant network interface data
3376  * @dev: peer device object
3377  *
3378  * Notify listeners about find a p2p peer device found
3379  */
3380 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
3381                                         const u8 *dev_addr)
3382 {
3383         wpas_dbus_signal_peer(wpa_s, dev_addr,
3384                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3385                               "DeviceFound");
3386 }
3387
3388 /**
3389  * wpas_dbus_signal_peer_lost - Send a peer lost signal
3390  * @wpa_s: %wpa_supplicant network interface data
3391  * @dev: peer device object
3392  *
3393  * Notify listeners about lost a p2p peer device
3394  */
3395 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
3396                                        const u8 *dev_addr)
3397 {
3398         wpas_dbus_signal_peer(wpa_s, dev_addr,
3399                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3400                               "DeviceLost");
3401 }
3402
3403 /**
3404  * wpas_dbus_register_peer - Register a discovered peer object with dbus
3405  * @wpa_s: wpa_supplicant interface structure
3406  * @ssid: network configuration data
3407  * Returns: 0 on success, -1 on failure
3408  *
3409  * Registers network representing object with dbus
3410  */
3411 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
3412 {
3413         struct wpas_dbus_priv *ctrl_iface;
3414         struct wpa_dbus_object_desc *obj_desc;
3415         struct peer_handler_args *arg;
3416         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3417
3418         /* Do nothing if the control interface is not turned on */
3419         if (wpa_s == NULL || wpa_s->global == NULL)
3420                 return 0;
3421
3422         ctrl_iface = wpa_s->global->dbus;
3423         if (ctrl_iface == NULL)
3424                 return 0;
3425
3426         if (wpa_s->p2p_mgmt)
3427                 wpa_s = wpa_s->parent;
3428
3429         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3430                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3431                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3432
3433         wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
3434                    peer_obj_path);
3435         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3436         if (!obj_desc) {
3437                 wpa_printf(MSG_ERROR,
3438                            "Not enough memory to create object description");
3439                 goto err;
3440         }
3441
3442         /* allocate memory for handlers arguments */
3443         arg = os_zalloc(sizeof(struct peer_handler_args));
3444         if (!arg) {
3445                 wpa_printf(MSG_ERROR,
3446                            "Not enough memory to create arguments for method");
3447                 goto err;
3448         }
3449
3450         arg->wpa_s = wpa_s;
3451         os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
3452
3453         wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
3454                            NULL,
3455                            wpas_dbus_p2p_peer_properties,
3456                            wpas_dbus_p2p_peer_signals);
3457
3458         if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
3459                                                wpa_s->ifname, obj_desc))
3460                 goto err;
3461
3462         return 0;
3463
3464 err:
3465         free_dbus_object_desc(obj_desc);
3466         return -1;
3467 }
3468
3469 /**
3470  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
3471  * @wpa_s: wpa_supplicant interface structure
3472  * @dev_addr: p2p device addr
3473  * Returns: 0 on success, -1 on failure
3474  *
3475  * Registers network representing object with dbus
3476  */
3477 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
3478                                   const u8 *dev_addr)
3479 {
3480         struct wpas_dbus_priv *ctrl_iface;
3481         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3482         int ret;
3483
3484         /* Do nothing if the control interface is not turned on */
3485         if (wpa_s == NULL || wpa_s->global == NULL ||
3486             wpa_s->dbus_new_path == NULL)
3487                 return 0;
3488
3489         if (wpa_s->p2p_mgmt)
3490                 wpa_s = wpa_s->parent;
3491
3492         ctrl_iface = wpa_s->global->dbus;
3493         if (ctrl_iface == NULL)
3494                 return 0;
3495
3496         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3497                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3498                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3499
3500         wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
3501                    peer_obj_path);
3502         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
3503
3504         return ret;
3505 }
3506
3507
3508 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
3509                                           const u8 *dev_addr)
3510 {
3511         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3512
3513         if (wpa_s->p2p_mgmt)
3514                 wpa_s = wpa_s->parent;
3515
3516         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3517                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3518                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3519
3520         wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
3521                                        WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
3522 }
3523
3524
3525 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
3526         { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
3527           wpas_dbus_getter_p2p_group_members,
3528           NULL
3529         },
3530         { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
3531           wpas_dbus_getter_p2p_group,
3532           NULL
3533         },
3534         { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3535           wpas_dbus_getter_p2p_role,
3536           NULL
3537         },
3538         { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3539           wpas_dbus_getter_p2p_group_ssid,
3540           NULL
3541         },
3542         { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3543           wpas_dbus_getter_p2p_group_bssid,
3544           NULL
3545         },
3546         { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
3547           wpas_dbus_getter_p2p_group_frequency,
3548           NULL
3549         },
3550         { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3551           wpas_dbus_getter_p2p_group_passphrase,
3552           NULL
3553         },
3554         { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3555           wpas_dbus_getter_p2p_group_psk,
3556           NULL
3557         },
3558         { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
3559           wpas_dbus_getter_p2p_group_vendor_ext,
3560           wpas_dbus_setter_p2p_group_vendor_ext
3561         },
3562         { NULL, NULL, NULL, NULL, NULL }
3563 };
3564
3565 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
3566         { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3567           {
3568                   { "peer", "o", ARG_OUT },
3569                   END_ARGS
3570           }
3571         },
3572         { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3573           {
3574                   { "peer", "o", ARG_OUT },
3575                   END_ARGS
3576           }
3577         },
3578         { NULL, NULL, { END_ARGS } }
3579 };
3580
3581 /**
3582  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
3583  * @wpa_s: wpa_supplicant interface structure
3584  * @ssid: SSID struct
3585  * Returns: 0 on success, -1 on failure
3586  *
3587  * Registers p2p group representing object with dbus
3588  */
3589 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
3590                                   struct wpa_ssid *ssid)
3591 {
3592         struct wpas_dbus_priv *ctrl_iface;
3593         struct wpa_dbus_object_desc *obj_desc;
3594         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3595
3596         /* Do nothing if the control interface is not turned on */
3597         if (wpa_s == NULL || wpa_s->global == NULL)
3598                 return;
3599
3600         ctrl_iface = wpa_s->global->dbus;
3601         if (ctrl_iface == NULL)
3602                 return;
3603
3604         if (wpa_s->dbus_groupobj_path) {
3605                 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
3606                            __func__, wpa_s->dbus_groupobj_path);
3607                 return;
3608         }
3609
3610         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
3611                 return;
3612
3613         wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
3614         if (wpa_s->dbus_groupobj_path == NULL)
3615                 return;
3616
3617         wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
3618                    group_obj_path);
3619         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3620         if (!obj_desc) {
3621                 wpa_printf(MSG_ERROR,
3622                            "Not enough memory to create object description");
3623                 goto err;
3624         }
3625
3626         wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
3627                            wpas_dbus_p2p_group_properties,
3628                            wpas_dbus_p2p_group_signals);
3629
3630         if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3631                                                wpa_s->ifname, obj_desc))
3632                 goto err;
3633
3634         return;
3635
3636 err:
3637         if (wpa_s->dbus_groupobj_path) {
3638                 os_free(wpa_s->dbus_groupobj_path);
3639                 wpa_s->dbus_groupobj_path = NULL;
3640         }
3641
3642         free_dbus_object_desc(obj_desc);
3643 }
3644
3645 /**
3646  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3647  * @wpa_s: wpa_supplicant interface structure
3648  * @ssid: network name of the p2p group started
3649  */
3650 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3651                                     const struct wpa_ssid *ssid)
3652 {
3653         struct wpas_dbus_priv *ctrl_iface;
3654
3655         /* Do nothing if the control interface is not turned on */
3656         if (wpa_s == NULL || wpa_s->global == NULL)
3657                 return;
3658
3659         if (wpa_s->p2p_mgmt)
3660                 wpa_s = wpa_s->parent;
3661
3662         ctrl_iface = wpa_s->global->dbus;
3663         if (ctrl_iface == NULL)
3664                 return;
3665
3666         if (!wpa_s->dbus_groupobj_path) {
3667                 wpa_printf(MSG_DEBUG,
3668                            "%s: Group object '%s' already unregistered",
3669                            __func__, wpa_s->dbus_groupobj_path);
3670                 return;
3671         }
3672
3673         peer_groups_changed(wpa_s);
3674
3675         wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3676                    wpa_s->dbus_groupobj_path);
3677
3678         wpa_dbus_unregister_object_per_iface(ctrl_iface,
3679                                              wpa_s->dbus_groupobj_path);
3680
3681         os_free(wpa_s->dbus_groupobj_path);
3682         wpa_s->dbus_groupobj_path = NULL;
3683 }
3684
3685 static const struct wpa_dbus_property_desc
3686         wpas_dbus_persistent_group_properties[] = {
3687         { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3688           wpas_dbus_getter_persistent_group_properties,
3689           wpas_dbus_setter_persistent_group_properties
3690         },
3691         { NULL, NULL, NULL, NULL, NULL }
3692 };
3693
3694 /* No signals intended for persistent group objects */
3695
3696 /**
3697  * wpas_dbus_register_persistent_group - Register a configured(saved)
3698  *      persistent group with dbus
3699  * @wpa_s: wpa_supplicant interface structure
3700  * @ssid: persistent group (still represented as a network within wpa)
3701  *        configuration data
3702  * Returns: 0 on success, -1 on failure
3703  *
3704  * Registers a persistent group representing object with dbus.
3705  */
3706 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3707                                         struct wpa_ssid *ssid)
3708 {
3709         struct wpas_dbus_priv *ctrl_iface;
3710         struct wpa_dbus_object_desc *obj_desc;
3711         struct network_handler_args *arg;
3712         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3713
3714         /* Do nothing if the control interface is not turned on */
3715         if (wpa_s == NULL || wpa_s->global == NULL)
3716                 return 0;
3717
3718         /* Make sure ssid is a persistent group */
3719         if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3720                 return -1; /* should we return w/o complaining? */
3721
3722         if (wpa_s->p2p_mgmt)
3723                 wpa_s = wpa_s->parent;
3724
3725         ctrl_iface = wpa_s->global->dbus;
3726         if (ctrl_iface == NULL)
3727                 return 0;
3728
3729         /*
3730          * Intentionally not coming up with different numbering scheme
3731          * for persistent groups.
3732          */
3733         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3734                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3735                     wpa_s->dbus_new_path, ssid->id);
3736
3737         wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3738                    pgrp_obj_path);
3739         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3740         if (!obj_desc) {
3741                 wpa_printf(MSG_ERROR,
3742                            "dbus: Not enough memory to create object description");
3743                 goto err;
3744         }
3745
3746         /*
3747          * Reusing the same context structure as that for networks
3748          * since these are represented using same data structure.
3749          */
3750         /* allocate memory for handlers arguments */
3751         arg = os_zalloc(sizeof(struct network_handler_args));
3752         if (!arg) {
3753                 wpa_printf(MSG_ERROR,
3754                            "dbus: Not enough memory to create arguments for method");
3755                 goto err;
3756         }
3757
3758         arg->wpa_s = wpa_s;
3759         arg->ssid = ssid;
3760
3761         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3762                            wpas_dbus_persistent_group_properties,
3763                            NULL);
3764
3765         if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3766                                                wpa_s->ifname, obj_desc))
3767                 goto err;
3768
3769         wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3770
3771         return 0;
3772
3773 err:
3774         free_dbus_object_desc(obj_desc);
3775         return -1;
3776 }
3777
3778
3779 /**
3780  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3781  *      from dbus
3782  * @wpa_s: wpa_supplicant interface structure
3783  * @nid: network id
3784  * Returns: 0 on success, -1 on failure
3785  *
3786  * Unregisters persistent group representing object from dbus
3787  *
3788  * NOTE: There is a slight issue with the semantics here. While the
3789  * implementation simply means the persistent group is unloaded from memory,
3790  * it should not get interpreted as the group is actually being erased/removed
3791  * from persistent storage as well.
3792  */
3793 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3794                                           int nid)
3795 {
3796         struct wpas_dbus_priv *ctrl_iface;
3797         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3798         int ret;
3799
3800         /* Do nothing if the control interface is not turned on */
3801         if (wpa_s == NULL || wpa_s->global == NULL ||
3802             wpa_s->dbus_new_path == NULL)
3803                 return 0;
3804
3805         if (wpa_s->p2p_mgmt)
3806                 wpa_s = wpa_s->parent;
3807
3808         ctrl_iface = wpa_s->global->dbus;
3809         if (ctrl_iface == NULL)
3810                 return 0;
3811
3812         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3813                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3814                     wpa_s->dbus_new_path, nid);
3815
3816         wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3817                    pgrp_obj_path);
3818         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3819
3820         if (!ret)
3821                 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3822
3823         return ret;
3824 }
3825
3826 #endif /* CONFIG_P2P */