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