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