dbus: Add SignalPoll() method to report current signal properties
[mech_eap.git] / wpa_supplicant / dbus / dbus_new.c
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "wps/wps.h"
16 #include "../config.h"
17 #include "../wpa_supplicant_i.h"
18 #include "../bss.h"
19 #include "../wpas_glue.h"
20 #include "dbus_new_helpers.h"
21 #include "dbus_dict_helpers.h"
22 #include "dbus_new.h"
23 #include "dbus_new_handlers.h"
24 #include "dbus_common_i.h"
25 #include "dbus_new_handlers_p2p.h"
26 #include "p2p/p2p.h"
27 #include "../p2p_supplicant.h"
28
29 #ifdef CONFIG_AP /* until needed by something else */
30
31 /*
32  * NameOwnerChanged handling
33  *
34  * Some services we provide allow an application to register for
35  * a signal that it needs. While it can also unregister, we must
36  * be prepared for the case where the application simply crashes
37  * and thus doesn't clean up properly. The way to handle this in
38  * DBus is to register for the NameOwnerChanged signal which will
39  * signal an owner change to NULL if the peer closes the socket
40  * for whatever reason.
41  *
42  * Handle this signal via a filter function whenever necessary.
43  * The code below also handles refcounting in case in the future
44  * there will be multiple instances of this subscription scheme.
45  */
46 static const char wpas_dbus_noc_filter_str[] =
47         "interface=org.freedesktop.DBus,member=NameOwnerChanged";
48
49
50 static DBusHandlerResult noc_filter(DBusConnection *conn,
51                                     DBusMessage *message, void *data)
52 {
53         struct wpas_dbus_priv *priv = data;
54
55         if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
56                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
57
58         if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
59                                    "NameOwnerChanged")) {
60                 const char *name;
61                 const char *prev_owner;
62                 const char *new_owner;
63                 DBusError derr;
64                 struct wpa_supplicant *wpa_s;
65
66                 dbus_error_init(&derr);
67
68                 if (!dbus_message_get_args(message, &derr,
69                                            DBUS_TYPE_STRING, &name,
70                                            DBUS_TYPE_STRING, &prev_owner,
71                                            DBUS_TYPE_STRING, &new_owner,
72                                            DBUS_TYPE_INVALID)) {
73                         /* Ignore this error */
74                         dbus_error_free(&derr);
75                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
76                 }
77
78                 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next)
79                 {
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         { NULL, NULL, NULL, NULL, NULL }
2101 };
2102
2103 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2104         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2105           {
2106                   { "path", "o", ARG_OUT },
2107                   { "properties", "a{sv}", ARG_OUT },
2108                   END_ARGS
2109           }
2110         },
2111         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2112           {
2113                   { "path", "o", ARG_OUT },
2114                   END_ARGS
2115           }
2116         },
2117         { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
2118           {
2119                   { "path", "o", ARG_OUT },
2120                   { "field", "s", ARG_OUT },
2121                   { "text", "s", ARG_OUT },
2122                   END_ARGS
2123           }
2124         },
2125         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2126         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2127           {
2128                   { "properties", "a{sv}", ARG_OUT },
2129                   END_ARGS
2130           }
2131         },
2132         { NULL, NULL, { END_ARGS } }
2133 };
2134
2135
2136 /**
2137  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2138  * @global: Pointer to global data from wpa_supplicant_init()
2139  * Returns: 0 on success or -1 on failure
2140  *
2141  * Initialize the dbus control interface for wpa_supplicantand and start
2142  * receiving commands from external programs over the bus.
2143  */
2144 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2145 {
2146         struct wpa_dbus_object_desc *obj_desc;
2147         int ret;
2148
2149         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2150         if (!obj_desc) {
2151                 wpa_printf(MSG_ERROR, "Not enough memory "
2152                            "to create object description");
2153                 return -1;
2154         }
2155
2156         wpas_dbus_register(obj_desc, priv->global, NULL,
2157                            wpas_dbus_global_methods,
2158                            wpas_dbus_global_properties,
2159                            wpas_dbus_global_signals);
2160
2161         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2162                    WPAS_DBUS_NEW_PATH);
2163         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2164                                        WPAS_DBUS_NEW_SERVICE,
2165                                        obj_desc);
2166         if (ret < 0)
2167                 free_dbus_object_desc(obj_desc);
2168         else
2169                 priv->dbus_new_initialized = 1;
2170
2171         return ret;
2172 }
2173
2174
2175 /**
2176  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2177  * wpa_supplicant
2178  * @iface: Pointer to dbus private data from wpas_dbus_init()
2179  *
2180  * Deinitialize the dbus control interface that was initialized with
2181  * wpas_dbus_ctrl_iface_init().
2182  */
2183 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
2184 {
2185         if (!iface->dbus_new_initialized)
2186                 return;
2187         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2188                    WPAS_DBUS_NEW_PATH);
2189         dbus_connection_unregister_object_path(iface->con,
2190                                                WPAS_DBUS_NEW_PATH);
2191 }
2192
2193
2194 static void wpa_dbus_free(void *ptr)
2195 {
2196         os_free(ptr);
2197 }
2198
2199
2200 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2201         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2202           wpas_dbus_getter_network_properties,
2203           wpas_dbus_setter_network_properties
2204         },
2205         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2206           wpas_dbus_getter_enabled,
2207           wpas_dbus_setter_enabled
2208         },
2209         { NULL, NULL, NULL, NULL, NULL }
2210 };
2211
2212
2213 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2214         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2215         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2216           {
2217                   { "properties", "a{sv}", ARG_OUT },
2218                   END_ARGS
2219           }
2220         },
2221         { NULL, NULL, { END_ARGS } }
2222 };
2223
2224
2225 /**
2226  * wpas_dbus_register_network - Register a configured network with dbus
2227  * @wpa_s: wpa_supplicant interface structure
2228  * @ssid: network configuration data
2229  * Returns: 0 on success, -1 on failure
2230  *
2231  * Registers network representing object with dbus
2232  */
2233 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2234                                struct wpa_ssid *ssid)
2235 {
2236         struct wpas_dbus_priv *ctrl_iface;
2237         struct wpa_dbus_object_desc *obj_desc;
2238         struct network_handler_args *arg;
2239         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2240
2241 #ifdef CONFIG_P2P
2242         /*
2243          * If it is a persistent group register it as such.
2244          * This is to handle cases where an interface is being initialized
2245          * with a list of networks read from config.
2246          */
2247         if (network_is_persistent_group(ssid))
2248                 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2249 #endif /* CONFIG_P2P */
2250
2251         /* Do nothing if the control interface is not turned on */
2252         if (wpa_s == NULL || wpa_s->global == NULL)
2253                 return 0;
2254         ctrl_iface = wpa_s->global->dbus;
2255         if (ctrl_iface == NULL)
2256                 return 0;
2257
2258         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2259                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2260                     wpa_s->dbus_new_path, ssid->id);
2261
2262         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2263                    net_obj_path);
2264         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2265         if (!obj_desc) {
2266                 wpa_printf(MSG_ERROR, "Not enough memory "
2267                            "to create object description");
2268                 goto err;
2269         }
2270
2271         /* allocate memory for handlers arguments */
2272         arg = os_zalloc(sizeof(struct network_handler_args));
2273         if (!arg) {
2274                 wpa_printf(MSG_ERROR, "Not enough memory "
2275                            "to create arguments for method");
2276                 goto err;
2277         }
2278
2279         arg->wpa_s = wpa_s;
2280         arg->ssid = ssid;
2281
2282         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2283                            wpas_dbus_network_properties,
2284                            wpas_dbus_network_signals);
2285
2286         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2287                                                wpa_s->ifname, obj_desc))
2288                 goto err;
2289
2290         wpas_dbus_signal_network_added(wpa_s, ssid->id);
2291
2292         return 0;
2293
2294 err:
2295         free_dbus_object_desc(obj_desc);
2296         return -1;
2297 }
2298
2299
2300 /**
2301  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2302  * @wpa_s: wpa_supplicant interface structure
2303  * @nid: network id
2304  * Returns: 0 on success, -1 on failure
2305  *
2306  * Unregisters network representing object from dbus
2307  */
2308 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2309 {
2310         struct wpas_dbus_priv *ctrl_iface;
2311         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2312         int ret;
2313 #ifdef CONFIG_P2P
2314         struct wpa_ssid *ssid;
2315
2316         ssid = wpa_config_get_network(wpa_s->conf, nid);
2317
2318         /* If it is a persistent group unregister it as such */
2319         if (ssid && network_is_persistent_group(ssid))
2320                 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2321 #endif /* CONFIG_P2P */
2322
2323         /* Do nothing if the control interface is not turned on */
2324         if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2325                 return 0;
2326         ctrl_iface = wpa_s->global->dbus;
2327         if (ctrl_iface == NULL)
2328                 return 0;
2329
2330         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2331                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2332                     wpa_s->dbus_new_path, nid);
2333
2334         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2335                    net_obj_path);
2336         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2337
2338         if (!ret)
2339                 wpas_dbus_signal_network_removed(wpa_s, nid);
2340
2341         return ret;
2342 }
2343
2344
2345 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2346         { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2347           wpas_dbus_getter_bss_ssid,
2348           NULL
2349         },
2350         { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2351           wpas_dbus_getter_bss_bssid,
2352           NULL
2353         },
2354         { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2355           wpas_dbus_getter_bss_privacy,
2356           NULL
2357         },
2358         { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2359           wpas_dbus_getter_bss_mode,
2360           NULL
2361         },
2362         { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2363           wpas_dbus_getter_bss_signal,
2364           NULL
2365         },
2366         { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2367           wpas_dbus_getter_bss_frequency,
2368           NULL
2369         },
2370         { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2371           wpas_dbus_getter_bss_rates,
2372           NULL
2373         },
2374         { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2375           wpas_dbus_getter_bss_wpa,
2376           NULL
2377         },
2378         { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2379           wpas_dbus_getter_bss_rsn,
2380           NULL
2381         },
2382         { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2383           wpas_dbus_getter_bss_wps,
2384           NULL
2385         },
2386         { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2387           wpas_dbus_getter_bss_ies,
2388           NULL
2389         },
2390         { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2391           wpas_dbus_getter_bss_age,
2392           NULL
2393         },
2394         { NULL, NULL, NULL, NULL, NULL }
2395 };
2396
2397
2398 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2399         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2400         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2401           {
2402                   { "properties", "a{sv}", ARG_OUT },
2403                   END_ARGS
2404           }
2405         },
2406         { NULL, NULL, { END_ARGS } }
2407 };
2408
2409
2410 /**
2411  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2412  * @wpa_s: wpa_supplicant interface structure
2413  * @bssid: scanned network bssid
2414  * @id: unique BSS identifier
2415  * Returns: 0 on success, -1 on failure
2416  *
2417  * Unregisters BSS representing object from dbus
2418  */
2419 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2420                              u8 bssid[ETH_ALEN], unsigned int id)
2421 {
2422         struct wpas_dbus_priv *ctrl_iface;
2423         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2424
2425         /* Do nothing if the control interface is not turned on */
2426         if (wpa_s == NULL || wpa_s->global == NULL)
2427                 return 0;
2428         ctrl_iface = wpa_s->global->dbus;
2429         if (ctrl_iface == NULL)
2430                 return 0;
2431
2432         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2433                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2434                     wpa_s->dbus_new_path, id);
2435
2436         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2437                    bss_obj_path);
2438         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2439                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2440                            bss_obj_path);
2441                 return -1;
2442         }
2443
2444         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2445         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2446
2447         return 0;
2448 }
2449
2450
2451 /**
2452  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2453  * @wpa_s: wpa_supplicant interface structure
2454  * @bssid: scanned network bssid
2455  * @id: unique BSS identifier
2456  * Returns: 0 on success, -1 on failure
2457  *
2458  * Registers BSS representing object with dbus
2459  */
2460 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2461                            u8 bssid[ETH_ALEN], unsigned int id)
2462 {
2463         struct wpas_dbus_priv *ctrl_iface;
2464         struct wpa_dbus_object_desc *obj_desc;
2465         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2466         struct bss_handler_args *arg;
2467
2468         /* Do nothing if the control interface is not turned on */
2469         if (wpa_s == NULL || wpa_s->global == NULL)
2470                 return 0;
2471         ctrl_iface = wpa_s->global->dbus;
2472         if (ctrl_iface == NULL)
2473                 return 0;
2474
2475         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2476                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2477                     wpa_s->dbus_new_path, id);
2478
2479         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2480         if (!obj_desc) {
2481                 wpa_printf(MSG_ERROR, "Not enough memory "
2482                            "to create object description");
2483                 goto err;
2484         }
2485
2486         arg = os_zalloc(sizeof(struct bss_handler_args));
2487         if (!arg) {
2488                 wpa_printf(MSG_ERROR, "Not enough memory "
2489                            "to create arguments for handler");
2490                 goto err;
2491         }
2492         arg->wpa_s = wpa_s;
2493         arg->id = id;
2494
2495         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2496                            wpas_dbus_bss_properties,
2497                            wpas_dbus_bss_signals);
2498
2499         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2500                    bss_obj_path);
2501         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2502                                                wpa_s->ifname, obj_desc)) {
2503                 wpa_printf(MSG_ERROR,
2504                            "Cannot register BSSID dbus object %s.",
2505                            bss_obj_path);
2506                 goto err;
2507         }
2508
2509         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2510         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2511
2512         return 0;
2513
2514 err:
2515         free_dbus_object_desc(obj_desc);
2516         return -1;
2517 }
2518
2519
2520 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2521         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2522           (WPADBusMethodHandler) &wpas_dbus_handler_scan,
2523           {
2524                   { "args", "a{sv}", ARG_IN },
2525                   END_ARGS
2526           }
2527         },
2528         { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
2529           (WPADBusMethodHandler) &wpas_dbus_handler_signal_poll,
2530           {
2531                   { "args", "a{sv}", ARG_OUT },
2532                   END_ARGS
2533           }
2534         },
2535         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2536           (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
2537           {
2538                   END_ARGS
2539           }
2540         },
2541         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2542           (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
2543           {
2544                   { "args", "a{sv}", ARG_IN },
2545                   { "path", "o", ARG_OUT },
2546                   END_ARGS
2547           }
2548         },
2549         { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
2550           (WPADBusMethodHandler) &wpas_dbus_handler_reassociate,
2551           {
2552                   END_ARGS
2553           }
2554         },
2555         { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
2556           (WPADBusMethodHandler) &wpas_dbus_handler_reattach,
2557           {
2558                   END_ARGS
2559           }
2560         },
2561         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2562           (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
2563           {
2564                   { "path", "o", ARG_IN },
2565                   END_ARGS
2566           }
2567         },
2568         { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2569           (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
2570           {
2571                   END_ARGS
2572           }
2573         },
2574         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2575           (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
2576           {
2577                   { "path", "o", ARG_IN },
2578                   END_ARGS
2579           }
2580         },
2581         { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2582           (WPADBusMethodHandler) &wpas_dbus_handler_network_reply,
2583           {
2584                   { "path", "o", ARG_IN },
2585                   { "field", "s", ARG_IN },
2586                   { "value", "s", ARG_IN },
2587                   END_ARGS
2588           }
2589         },
2590 #ifndef CONFIG_NO_CONFIG_BLOBS
2591         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2592           (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
2593           {
2594                   { "name", "s", ARG_IN },
2595                   { "data", "ay", ARG_IN },
2596                   END_ARGS
2597           }
2598         },
2599         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2600           (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
2601           {
2602                   { "name", "s", ARG_IN },
2603                   { "data", "ay", ARG_OUT },
2604                   END_ARGS
2605           }
2606         },
2607         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2608           (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
2609           {
2610                   { "name", "s", ARG_IN },
2611                   END_ARGS
2612           }
2613         },
2614 #endif /* CONFIG_NO_CONFIG_BLOBS */
2615         { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
2616           (WPADBusMethodHandler)
2617           &wpas_dbus_handler_set_pkcs11_engine_and_module_path,
2618           {
2619                   { "pkcs11_engine_path", "s", ARG_IN },
2620                   { "pkcs11_module_path", "s", ARG_IN },
2621                   END_ARGS
2622           }
2623         },
2624 #ifdef CONFIG_WPS
2625         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
2626           (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
2627           {
2628                   { "args", "a{sv}", ARG_IN },
2629                   { "output", "a{sv}", ARG_OUT },
2630                   END_ARGS
2631           }
2632         },
2633 #endif /* CONFIG_WPS */
2634 #ifdef CONFIG_P2P
2635         { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2636           (WPADBusMethodHandler)wpas_dbus_handler_p2p_find,
2637           {
2638                   { "args", "a{sv}", ARG_IN },
2639                   END_ARGS
2640           }
2641         },
2642         { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2643           (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find,
2644           {
2645                   END_ARGS
2646           }
2647         },
2648         { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2649           (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen,
2650           {
2651                   { "timeout", "i", ARG_IN },
2652                   END_ARGS
2653           }
2654         },
2655         { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2656           (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten,
2657           {
2658                   { "args", "a{sv}", ARG_IN },
2659                   END_ARGS
2660           }
2661         },
2662         { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2663           (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request,
2664           {
2665                   { "args", "a{sv}", ARG_IN },
2666                   END_ARGS
2667           }
2668         },
2669         { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2670           (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req,
2671           {
2672                   { "peer", "o", ARG_IN },
2673                   { "config_method", "s", ARG_IN },
2674                   END_ARGS
2675           }
2676         },
2677         { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2678           (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect,
2679           {
2680                   { "args", "a{sv}", ARG_IN },
2681                   { "generated_pin", "s", ARG_OUT },
2682                   END_ARGS
2683           }
2684         },
2685         { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2686           (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add,
2687           {
2688                   { "args", "a{sv}", ARG_IN },
2689                   END_ARGS
2690           }
2691         },
2692         { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2693           (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite,
2694           {
2695                   { "args", "a{sv}", ARG_IN },
2696                   END_ARGS
2697           }
2698         },
2699         { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2700           (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect,
2701           {
2702                   END_ARGS
2703           }
2704         },
2705         { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2706           (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer,
2707           {
2708                   { "peer", "o", ARG_IN },
2709                   END_ARGS
2710           }
2711         },
2712         { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2713           (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush,
2714           {
2715                   END_ARGS
2716           }
2717         },
2718         { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2719           (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service,
2720           {
2721                   { "args", "a{sv}", ARG_IN },
2722                   END_ARGS
2723           }
2724         },
2725         { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2726           (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service,
2727           {
2728                   { "args", "a{sv}", ARG_IN },
2729                   END_ARGS
2730           }
2731         },
2732         { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2733           (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service,
2734           {
2735                   END_ARGS
2736           }
2737         },
2738         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2739           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
2740           {
2741                   { "args", "a{sv}", ARG_IN },
2742                   { "ref", "t", ARG_OUT },
2743                   END_ARGS
2744           }
2745         },
2746         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2747           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res,
2748           {
2749                   { "args", "a{sv}", ARG_IN },
2750                   END_ARGS
2751           }
2752         },
2753         { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2754           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req,
2755           {
2756                   { "args", "t", ARG_IN },
2757                   END_ARGS
2758           }
2759         },
2760         { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2761           (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update,
2762           {
2763                   END_ARGS
2764           }
2765         },
2766         { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2767           (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2768           {
2769                   { "arg", "i", ARG_IN },
2770                   END_ARGS
2771           }
2772         },
2773         { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2774           (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2775           {
2776                   { "args", "a{sv}", ARG_IN },
2777                   { "path", "o", ARG_OUT },
2778                   END_ARGS
2779           }
2780         },
2781         { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2782           (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
2783           {
2784                   { "path", "o", ARG_IN },
2785                   END_ARGS
2786           }
2787         },
2788         { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2789           (WPADBusMethodHandler)
2790           wpas_dbus_handler_remove_all_persistent_groups,
2791           {
2792                   END_ARGS
2793           }
2794         },
2795 #endif /* CONFIG_P2P */
2796         { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
2797           (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
2798           {
2799                   { "age", "u", ARG_IN },
2800                   END_ARGS
2801           }
2802         },
2803 #ifdef CONFIG_AP
2804         { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2805           (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
2806           {
2807                   END_ARGS
2808           }
2809         },
2810         { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2811           (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
2812           {
2813                   END_ARGS
2814           }
2815         },
2816 #endif /* CONFIG_AP */
2817         { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
2818           (WPADBusMethodHandler) &wpas_dbus_handler_eap_logoff,
2819           {
2820                   END_ARGS
2821           }
2822         },
2823         { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
2824           (WPADBusMethodHandler) &wpas_dbus_handler_eap_logon,
2825           {
2826                   END_ARGS
2827           }
2828         },
2829 #ifdef CONFIG_AUTOSCAN
2830         { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2831           (WPADBusMethodHandler) &wpas_dbus_handler_autoscan,
2832           {
2833                   { "arg", "s", ARG_IN },
2834                   END_ARGS
2835           }
2836         },
2837 #endif /* CONFIG_AUTOSCAN */
2838 #ifdef CONFIG_TDLS
2839         { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
2840           (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
2841           {
2842                   { "peer_address", "s", ARG_IN },
2843                   END_ARGS
2844           }
2845         },
2846         { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
2847           (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
2848           {
2849                   { "peer_address", "s", ARG_IN },
2850                   END_ARGS
2851           }
2852         },
2853         { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
2854           (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
2855           {
2856                   { "peer_address", "s", ARG_IN },
2857                   { "status", "s", ARG_OUT },
2858                   END_ARGS
2859           }
2860         },
2861         { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
2862           (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
2863           {
2864                   { "peer_address", "s", ARG_IN },
2865                   END_ARGS
2866           }
2867         },
2868 #endif /* CONFIG_TDLS */
2869         { NULL, NULL, NULL, { END_ARGS } }
2870 };
2871
2872 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
2873         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
2874           wpas_dbus_getter_capabilities,
2875           NULL
2876         },
2877         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2878           wpas_dbus_getter_state,
2879           NULL
2880         },
2881         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2882           wpas_dbus_getter_scanning,
2883           NULL
2884         },
2885         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2886           wpas_dbus_getter_ap_scan,
2887           wpas_dbus_setter_ap_scan
2888         },
2889         { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2890           wpas_dbus_getter_bss_expire_age,
2891           wpas_dbus_setter_bss_expire_age
2892         },
2893         { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2894           wpas_dbus_getter_bss_expire_count,
2895           wpas_dbus_setter_bss_expire_count
2896         },
2897         { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2898           wpas_dbus_getter_country,
2899           wpas_dbus_setter_country
2900         },
2901         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2902           wpas_dbus_getter_ifname,
2903           NULL
2904         },
2905         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2906           wpas_dbus_getter_driver,
2907           NULL
2908         },
2909         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2910           wpas_dbus_getter_bridge_ifname,
2911           NULL
2912         },
2913         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2914           wpas_dbus_getter_current_bss,
2915           NULL
2916         },
2917         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2918           wpas_dbus_getter_current_network,
2919           NULL
2920         },
2921         { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2922           wpas_dbus_getter_current_auth_mode,
2923           NULL
2924         },
2925         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
2926           wpas_dbus_getter_blobs,
2927           NULL
2928         },
2929         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2930           wpas_dbus_getter_bsss,
2931           NULL
2932         },
2933         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2934           wpas_dbus_getter_networks,
2935           NULL
2936         },
2937         { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2938           wpas_dbus_getter_fast_reauth,
2939           wpas_dbus_setter_fast_reauth
2940         },
2941         { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2942           wpas_dbus_getter_scan_interval,
2943           wpas_dbus_setter_scan_interval
2944         },
2945         { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2946           wpas_dbus_getter_pkcs11_engine_path,
2947           NULL
2948         },
2949         { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2950           wpas_dbus_getter_pkcs11_module_path,
2951           NULL
2952         },
2953 #ifdef CONFIG_WPS
2954         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
2955           wpas_dbus_getter_process_credentials,
2956           wpas_dbus_setter_process_credentials
2957         },
2958 #endif /* CONFIG_WPS */
2959 #ifdef CONFIG_P2P
2960         { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
2961           wpas_dbus_getter_p2p_device_config,
2962           wpas_dbus_setter_p2p_device_config
2963         },
2964         { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2965           wpas_dbus_getter_p2p_peers,
2966           NULL
2967         },
2968         { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
2969           wpas_dbus_getter_p2p_role,
2970           NULL
2971         },
2972         { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2973           wpas_dbus_getter_p2p_group,
2974           NULL
2975         },
2976         { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2977           wpas_dbus_getter_p2p_peergo,
2978           NULL
2979         },
2980         { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2981           wpas_dbus_getter_persistent_groups,
2982           NULL
2983         },
2984 #endif /* CONFIG_P2P */
2985         { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2986           wpas_dbus_getter_disconnect_reason,
2987           NULL
2988         },
2989         { NULL, NULL, NULL, NULL, NULL }
2990 };
2991
2992 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
2993         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
2994           {
2995                   { "success", "b", ARG_OUT },
2996                   END_ARGS
2997           }
2998         },
2999         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3000           {
3001                   { "path", "o", ARG_OUT },
3002                   { "properties", "a{sv}", ARG_OUT },
3003                   END_ARGS
3004           }
3005         },
3006         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3007           {
3008                   { "path", "o", ARG_OUT },
3009                   END_ARGS
3010           }
3011         },
3012         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3013           {
3014                   { "name", "s", ARG_OUT },
3015                   END_ARGS
3016           }
3017         },
3018         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3019           {
3020                   { "name", "s", ARG_OUT },
3021                   END_ARGS
3022           }
3023         },
3024         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3025           {
3026                   { "path", "o", ARG_OUT },
3027                   { "properties", "a{sv}", ARG_OUT },
3028                   END_ARGS
3029           }
3030         },
3031         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3032           {
3033                   { "path", "o", ARG_OUT },
3034                   END_ARGS
3035           }
3036         },
3037         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
3038           {
3039                   { "path", "o", ARG_OUT },
3040                   END_ARGS
3041           }
3042         },
3043         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3044         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
3045           {
3046                   { "properties", "a{sv}", ARG_OUT },
3047                   END_ARGS
3048           }
3049         },
3050 #ifdef CONFIG_WPS
3051         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
3052           {
3053                   { "name", "s", ARG_OUT },
3054                   { "args", "a{sv}", ARG_OUT },
3055                   END_ARGS
3056           }
3057         },
3058         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
3059           {
3060                   { "credentials", "a{sv}", ARG_OUT },
3061                   END_ARGS
3062           }
3063         },
3064         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3065         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
3066           {
3067                   { "properties", "a{sv}", ARG_OUT },
3068                   END_ARGS
3069           }
3070         },
3071 #endif /* CONFIG_WPS */
3072 #ifdef CONFIG_P2P
3073         { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3074           {
3075                   { "states", "a{ss}", ARG_OUT },
3076                   END_ARGS
3077           }
3078         },
3079         { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3080           {
3081                   { "path", "o", ARG_OUT },
3082                   END_ARGS
3083           }
3084         },
3085         { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3086           {
3087                   { "path", "o", ARG_OUT },
3088                   END_ARGS
3089           }
3090         },
3091         { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3092           {
3093                   { "peer_object", "o", ARG_OUT },
3094                   { "pin", "s", ARG_OUT },
3095                   END_ARGS
3096           }
3097         },
3098         { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3099           {
3100                   { "peer_object", "o", ARG_OUT },
3101                   { "pin", "s", ARG_OUT },
3102                   END_ARGS
3103           }
3104         },
3105         { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3106           {
3107                   { "peer_object", "o", ARG_OUT },
3108                   END_ARGS
3109           }
3110         },
3111         { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3112           {
3113                   { "peer_object", "o", ARG_OUT },
3114                   END_ARGS
3115           }
3116         },
3117         { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3118           {
3119                   { "peer_object", "o", ARG_OUT },
3120                   END_ARGS
3121           }
3122         },
3123         { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3124           {
3125                   { "peer_object", "o", ARG_OUT },
3126                   END_ARGS
3127           }
3128         },
3129         { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3130           {
3131                   { "peer_object", "o", ARG_OUT },
3132                   { "status", "i", ARG_OUT },
3133                   END_ARGS
3134           }
3135         },
3136         { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3137           {
3138                   { "properties", "a{sv}", ARG_OUT },
3139                   END_ARGS
3140           }
3141         },
3142         { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3143           {
3144                   { "properties", "a{sv}", ARG_OUT },
3145                   END_ARGS
3146           }
3147         },
3148         { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3149           {
3150                   { "properties", "a{sv}", ARG_OUT },
3151                   END_ARGS
3152           }
3153         },
3154         { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3155           {
3156                   { "path", "o", ARG_OUT },
3157                   { "dev_passwd_id", "i", ARG_OUT },
3158                   END_ARGS
3159           }
3160         },
3161         { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3162           {
3163                   { "invite_result", "a{sv}", ARG_OUT },
3164                   END_ARGS
3165           }
3166         },
3167         { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3168           {
3169                   { "properties", "a{sv}", ARG_OUT },
3170                   END_ARGS
3171           }
3172         },
3173         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3174           {
3175                   { "sd_request", "a{sv}", ARG_OUT },
3176                   END_ARGS
3177           }
3178         },
3179         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3180           {
3181                   { "sd_response", "a{sv}", ARG_OUT },
3182                   END_ARGS
3183           }
3184         },
3185         { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3186           {
3187                   { "path", "o", ARG_OUT },
3188                   { "properties", "a{sv}", ARG_OUT },
3189                   END_ARGS
3190           }
3191         },
3192         { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3193           {
3194                   { "path", "o", ARG_OUT },
3195                   END_ARGS
3196           }
3197         },
3198         { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3199           {
3200                   { "name", "s", ARG_OUT },
3201                   { "args", "a{sv}", ARG_OUT },
3202                   END_ARGS
3203           }
3204         },
3205 #endif /* CONFIG_P2P */
3206 #ifdef CONFIG_AP
3207         { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
3208           {
3209                   { "args", "a{sv}", ARG_OUT },
3210                   END_ARGS
3211           }
3212         },
3213 #endif /* CONFIG_AP */
3214         { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
3215           {
3216                   { "certification", "a{sv}", ARG_OUT },
3217                   END_ARGS
3218           }
3219         },
3220         { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
3221           {
3222                   { "status", "s", ARG_OUT },
3223                   { "parameter", "s", ARG_OUT },
3224                   END_ARGS
3225           }
3226         },
3227         { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3228           {
3229                   { "name", "s", ARG_OUT },
3230                   END_ARGS
3231           }
3232         },
3233         { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3234           {
3235                   { "name", "s", ARG_OUT },
3236                   END_ARGS
3237           }
3238         },
3239         { NULL, NULL, { END_ARGS } }
3240 };
3241
3242
3243 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
3244 {
3245
3246         struct wpa_dbus_object_desc *obj_desc = NULL;
3247         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
3248         int next;
3249
3250         /* Do nothing if the control interface is not turned on */
3251         if (ctrl_iface == NULL)
3252                 return 0;
3253
3254         /* Create and set the interface's object path */
3255         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3256         if (wpa_s->dbus_new_path == NULL)
3257                 return -1;
3258         next = ctrl_iface->next_objid++;
3259         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
3260                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
3261                     next);
3262
3263         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3264         if (!obj_desc) {
3265                 wpa_printf(MSG_ERROR, "Not enough memory "
3266                            "to create object description");
3267                 goto err;
3268         }
3269
3270         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
3271                            wpas_dbus_interface_properties,
3272                            wpas_dbus_interface_signals);
3273
3274         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
3275                    wpa_s->dbus_new_path);
3276         if (wpa_dbus_register_object_per_iface(ctrl_iface,
3277                                                wpa_s->dbus_new_path,
3278                                                wpa_s->ifname, obj_desc))
3279                 goto err;
3280
3281         wpas_dbus_signal_interface_added(wpa_s);
3282
3283         return 0;
3284
3285 err:
3286         os_free(wpa_s->dbus_new_path);
3287         wpa_s->dbus_new_path = NULL;
3288         free_dbus_object_desc(obj_desc);
3289         return -1;
3290 }
3291
3292
3293 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
3294 {
3295         struct wpas_dbus_priv *ctrl_iface;
3296
3297         /* Do nothing if the control interface is not turned on */
3298         if (wpa_s == NULL || wpa_s->global == NULL)
3299                 return 0;
3300         ctrl_iface = wpa_s->global->dbus;
3301         if (ctrl_iface == NULL)
3302                 return 0;
3303
3304         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
3305                    wpa_s->dbus_new_path);
3306
3307 #ifdef CONFIG_AP
3308         if (wpa_s->preq_notify_peer) {
3309                 wpas_dbus_unsubscribe_noc(ctrl_iface);
3310                 os_free(wpa_s->preq_notify_peer);
3311                 wpa_s->preq_notify_peer = NULL;
3312         }
3313 #endif /* CONFIG_AP */
3314
3315         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3316                                                  wpa_s->dbus_new_path))
3317                 return -1;
3318
3319         wpas_dbus_signal_interface_removed(wpa_s);
3320
3321         os_free(wpa_s->dbus_new_path);
3322         wpa_s->dbus_new_path = NULL;
3323
3324         return 0;
3325 }
3326
3327 #ifdef CONFIG_P2P
3328
3329 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
3330         { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3331           wpas_dbus_getter_p2p_peer_device_name,
3332           NULL
3333         },
3334         { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3335           wpas_dbus_getter_p2p_peer_primary_device_type,
3336           NULL
3337         },
3338         { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
3339           wpas_dbus_getter_p2p_peer_config_method,
3340           NULL
3341         },
3342         { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
3343           wpas_dbus_getter_p2p_peer_level,
3344           NULL
3345         },
3346         { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3347           wpas_dbus_getter_p2p_peer_device_capability,
3348           NULL
3349         },
3350         { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3351           wpas_dbus_getter_p2p_peer_group_capability,
3352           NULL
3353         },
3354         { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3355           wpas_dbus_getter_p2p_peer_secondary_device_types,
3356           NULL
3357         },
3358         { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3359           wpas_dbus_getter_p2p_peer_vendor_extension,
3360           NULL
3361         },
3362         { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3363           wpas_dbus_getter_p2p_peer_ies,
3364           NULL
3365         },
3366         { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3367           wpas_dbus_getter_p2p_peer_device_address,
3368           NULL
3369         },
3370         { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
3371           wpas_dbus_getter_p2p_peer_groups,
3372           NULL
3373         },
3374         { NULL, NULL, NULL, NULL, NULL }
3375 };
3376
3377 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
3378         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3379         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
3380           {
3381                   { "properties", "a{sv}", ARG_OUT },
3382                   END_ARGS
3383           }
3384         },
3385         { NULL, NULL, { END_ARGS } }
3386 };
3387
3388 /**
3389  * wpas_dbus_signal_peer - Send a peer related event signal
3390  * @wpa_s: %wpa_supplicant network interface data
3391  * @dev: peer device object
3392  * @interface: name of the interface emitting this signal.
3393  *      In case of peer objects, it would be emitted by either
3394  *      the "interface object" or by "peer objects"
3395  * @sig_name: signal name - DeviceFound
3396  *
3397  * Notify listeners about event related with newly found p2p peer device
3398  */
3399 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
3400                                   const u8 *dev_addr, const char *interface,
3401                                   const char *sig_name)
3402 {
3403         struct wpas_dbus_priv *iface;
3404         DBusMessage *msg;
3405         DBusMessageIter iter;
3406         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
3407
3408         iface = wpa_s->global->dbus;
3409
3410         /* Do nothing if the control interface is not turned on */
3411         if (iface == NULL)
3412                 return;
3413
3414         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3415                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3416                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3417
3418         msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
3419                                       sig_name);
3420         if (msg == NULL)
3421                 return;
3422
3423         dbus_message_iter_init_append(msg, &iter);
3424         path = peer_obj_path;
3425         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
3426                                             &path))
3427                 goto err;
3428
3429         dbus_connection_send(iface->con, msg, NULL);
3430
3431         dbus_message_unref(msg);
3432         return;
3433
3434 err:
3435         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3436         dbus_message_unref(msg);
3437 }
3438
3439
3440 /**
3441  * wpas_dbus_signal_peer_found - Send a peer found signal
3442  * @wpa_s: %wpa_supplicant network interface data
3443  * @dev: peer device object
3444  *
3445  * Notify listeners about find a p2p peer device found
3446  */
3447 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
3448                                         const u8 *dev_addr)
3449 {
3450         wpas_dbus_signal_peer(wpa_s, dev_addr,
3451                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3452                               "DeviceFound");
3453 }
3454
3455 /**
3456  * wpas_dbus_signal_peer_lost - Send a peer lost signal
3457  * @wpa_s: %wpa_supplicant network interface data
3458  * @dev: peer device object
3459  *
3460  * Notify listeners about lost a p2p peer device
3461  */
3462 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
3463                                        const u8 *dev_addr)
3464 {
3465         wpas_dbus_signal_peer(wpa_s, dev_addr,
3466                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3467                               "DeviceLost");
3468 }
3469
3470 /**
3471  * wpas_dbus_register_peer - Register a discovered peer object with dbus
3472  * @wpa_s: wpa_supplicant interface structure
3473  * @ssid: network configuration data
3474  * Returns: 0 on success, -1 on failure
3475  *
3476  * Registers network representing object with dbus
3477  */
3478 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
3479 {
3480         struct wpas_dbus_priv *ctrl_iface;
3481         struct wpa_dbus_object_desc *obj_desc;
3482         struct peer_handler_args *arg;
3483         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3484
3485         /* Do nothing if the control interface is not turned on */
3486         if (wpa_s == NULL || wpa_s->global == NULL)
3487                 return 0;
3488
3489         ctrl_iface = wpa_s->global->dbus;
3490         if (ctrl_iface == NULL)
3491                 return 0;
3492
3493         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3494                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3495                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3496
3497         wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
3498                    peer_obj_path);
3499         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3500         if (!obj_desc) {
3501                 wpa_printf(MSG_ERROR, "Not enough memory "
3502                            "to create object description");
3503                 goto err;
3504         }
3505
3506         /* allocate memory for handlers arguments */
3507         arg = os_zalloc(sizeof(struct peer_handler_args));
3508         if (!arg) {
3509                 wpa_printf(MSG_ERROR, "Not enough memory "
3510                            "to create arguments for method");
3511                 goto err;
3512         }
3513
3514         arg->wpa_s = wpa_s;
3515         os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
3516
3517         wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
3518                            NULL,
3519                            wpas_dbus_p2p_peer_properties,
3520                            wpas_dbus_p2p_peer_signals);
3521
3522         if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
3523                                                wpa_s->ifname, obj_desc))
3524                 goto err;
3525
3526         return 0;
3527
3528 err:
3529         free_dbus_object_desc(obj_desc);
3530         return -1;
3531 }
3532
3533 /**
3534  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
3535  * @wpa_s: wpa_supplicant interface structure
3536  * @dev_addr: p2p device addr
3537  * Returns: 0 on success, -1 on failure
3538  *
3539  * Registers network representing object with dbus
3540  */
3541 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
3542                                   const u8 *dev_addr)
3543 {
3544         struct wpas_dbus_priv *ctrl_iface;
3545         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3546         int ret;
3547
3548         /* Do nothing if the control interface is not turned on */
3549         if (wpa_s == NULL || wpa_s->global == NULL ||
3550             wpa_s->dbus_new_path == NULL)
3551                 return 0;
3552         ctrl_iface = wpa_s->global->dbus;
3553         if (ctrl_iface == NULL)
3554                 return 0;
3555
3556         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3557                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3558                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3559
3560         wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
3561                    peer_obj_path);
3562         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
3563
3564         return ret;
3565 }
3566
3567
3568 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
3569                                           const u8 *dev_addr)
3570 {
3571         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3572
3573         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3574                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3575                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
3576
3577         wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
3578                                        WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
3579 }
3580
3581
3582 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
3583         { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
3584           wpas_dbus_getter_p2p_group_members,
3585           NULL
3586         },
3587         { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
3588           wpas_dbus_getter_p2p_group,
3589           NULL
3590         },
3591         { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3592           wpas_dbus_getter_p2p_role,
3593           NULL
3594         },
3595         { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3596           wpas_dbus_getter_p2p_group_ssid,
3597           NULL
3598         },
3599         { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3600           wpas_dbus_getter_p2p_group_bssid,
3601           NULL
3602         },
3603         { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
3604           wpas_dbus_getter_p2p_group_frequency,
3605           NULL
3606         },
3607         { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3608           wpas_dbus_getter_p2p_group_passphrase,
3609           NULL
3610         },
3611         { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3612           wpas_dbus_getter_p2p_group_psk,
3613           NULL
3614         },
3615         { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
3616           wpas_dbus_getter_p2p_group_vendor_ext,
3617           wpas_dbus_setter_p2p_group_vendor_ext
3618         },
3619         { NULL, NULL, NULL, NULL, NULL }
3620 };
3621
3622 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
3623         { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3624           {
3625                   { "peer", "o", ARG_OUT },
3626                   END_ARGS
3627           }
3628         },
3629         { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3630           {
3631                   { "peer", "o", ARG_OUT },
3632                   END_ARGS
3633           }
3634         },
3635         { NULL, NULL, { END_ARGS } }
3636 };
3637
3638 /**
3639  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
3640  * @wpa_s: wpa_supplicant interface structure
3641  * @ssid: SSID struct
3642  * Returns: 0 on success, -1 on failure
3643  *
3644  * Registers p2p group representing object with dbus
3645  */
3646 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
3647                                   struct wpa_ssid *ssid)
3648 {
3649         struct wpas_dbus_priv *ctrl_iface;
3650         struct wpa_dbus_object_desc *obj_desc;
3651         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3652
3653         /* Do nothing if the control interface is not turned on */
3654         if (wpa_s == NULL || wpa_s->global == NULL)
3655                 return;
3656
3657         ctrl_iface = wpa_s->global->dbus;
3658         if (ctrl_iface == NULL)
3659                 return;
3660
3661         if (wpa_s->dbus_groupobj_path) {
3662                 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
3663                            __func__, wpa_s->dbus_groupobj_path);
3664                 return;
3665         }
3666
3667         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
3668                 return;
3669
3670         wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
3671         if (wpa_s->dbus_groupobj_path == NULL)
3672                 return;
3673
3674         wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
3675                    group_obj_path);
3676         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3677         if (!obj_desc) {
3678                 wpa_printf(MSG_ERROR, "Not enough memory "
3679                            "to create object description");
3680                 goto err;
3681         }
3682
3683         wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
3684                            wpas_dbus_p2p_group_properties,
3685                            wpas_dbus_p2p_group_signals);
3686
3687         if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3688                                                wpa_s->ifname, obj_desc))
3689                 goto err;
3690
3691         return;
3692
3693 err:
3694         if (wpa_s->dbus_groupobj_path) {
3695                 os_free(wpa_s->dbus_groupobj_path);
3696                 wpa_s->dbus_groupobj_path = NULL;
3697         }
3698
3699         free_dbus_object_desc(obj_desc);
3700 }
3701
3702 /**
3703  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3704  * @wpa_s: wpa_supplicant interface structure
3705  * @ssid: network name of the p2p group started
3706  */
3707 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3708                                     const struct wpa_ssid *ssid)
3709 {
3710         struct wpas_dbus_priv *ctrl_iface;
3711
3712         /* Do nothing if the control interface is not turned on */
3713         if (wpa_s == NULL || wpa_s->global == NULL)
3714                 return;
3715
3716         ctrl_iface = wpa_s->global->dbus;
3717         if (ctrl_iface == NULL)
3718                 return;
3719
3720         if (!wpa_s->dbus_groupobj_path) {
3721                 wpa_printf(MSG_DEBUG,
3722                            "%s: Group object '%s' already unregistered",
3723                            __func__, wpa_s->dbus_groupobj_path);
3724                 return;
3725         }
3726
3727         peer_groups_changed(wpa_s);
3728
3729         wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3730                    wpa_s->dbus_groupobj_path);
3731
3732         wpa_dbus_unregister_object_per_iface(ctrl_iface,
3733                                              wpa_s->dbus_groupobj_path);
3734
3735         os_free(wpa_s->dbus_groupobj_path);
3736         wpa_s->dbus_groupobj_path = NULL;
3737 }
3738
3739 static const struct wpa_dbus_property_desc
3740         wpas_dbus_persistent_group_properties[] = {
3741         { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3742           wpas_dbus_getter_persistent_group_properties,
3743           wpas_dbus_setter_persistent_group_properties
3744         },
3745         { NULL, NULL, NULL, NULL, NULL }
3746 };
3747
3748 /* No signals intended for persistent group objects */
3749
3750 /**
3751  * wpas_dbus_register_persistent_group - Register a configured(saved)
3752  *      persistent group with dbus
3753  * @wpa_s: wpa_supplicant interface structure
3754  * @ssid: persistent group (still represented as a network within wpa)
3755  *        configuration data
3756  * Returns: 0 on success, -1 on failure
3757  *
3758  * Registers a persistent group representing object with dbus.
3759  */
3760 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3761                                         struct wpa_ssid *ssid)
3762 {
3763         struct wpas_dbus_priv *ctrl_iface;
3764         struct wpa_dbus_object_desc *obj_desc;
3765         struct network_handler_args *arg;
3766         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3767
3768         /* Do nothing if the control interface is not turned on */
3769         if (wpa_s == NULL || wpa_s->global == NULL)
3770                 return 0;
3771
3772         /* Make sure ssid is a persistent group */
3773         if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3774                 return -1; /* should we return w/o complaining? */
3775
3776         ctrl_iface = wpa_s->global->dbus;
3777         if (ctrl_iface == NULL)
3778                 return 0;
3779
3780         /*
3781          * Intentionally not coming up with different numbering scheme
3782          * for persistent groups.
3783          */
3784         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3785                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3786                     wpa_s->dbus_new_path, ssid->id);
3787
3788         wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3789                    pgrp_obj_path);
3790         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3791         if (!obj_desc) {
3792                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3793                            "object description");
3794                 goto err;
3795         }
3796
3797         /*
3798          * Reusing the same context structure as that for networks
3799          * since these are represented using same data structure.
3800          */
3801         /* allocate memory for handlers arguments */
3802         arg = os_zalloc(sizeof(struct network_handler_args));
3803         if (!arg) {
3804                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3805                            "arguments for method");
3806                 goto err;
3807         }
3808
3809         arg->wpa_s = wpa_s;
3810         arg->ssid = ssid;
3811
3812         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3813                            wpas_dbus_persistent_group_properties,
3814                            NULL);
3815
3816         if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3817                                                wpa_s->ifname, obj_desc))
3818                 goto err;
3819
3820         wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3821
3822         return 0;
3823
3824 err:
3825         free_dbus_object_desc(obj_desc);
3826         return -1;
3827 }
3828
3829
3830 /**
3831  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3832  *      from dbus
3833  * @wpa_s: wpa_supplicant interface structure
3834  * @nid: network id
3835  * Returns: 0 on success, -1 on failure
3836  *
3837  * Unregisters persistent group representing object from dbus
3838  *
3839  * NOTE: There is a slight issue with the semantics here. While the
3840  * implementation simply means the persistent group is unloaded from memory,
3841  * it should not get interpreted as the group is actually being erased/removed
3842  * from persistent storage as well.
3843  */
3844 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3845                                           int nid)
3846 {
3847         struct wpas_dbus_priv *ctrl_iface;
3848         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3849         int ret;
3850
3851         /* Do nothing if the control interface is not turned on */
3852         if (wpa_s == NULL || wpa_s->global == NULL ||
3853             wpa_s->dbus_new_path == NULL)
3854                 return 0;
3855         ctrl_iface = wpa_s->global->dbus;
3856         if (ctrl_iface == NULL)
3857                 return 0;
3858
3859         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3860                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3861                     wpa_s->dbus_new_path, nid);
3862
3863         wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3864                    pgrp_obj_path);
3865         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3866
3867         if (!ret)
3868                 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3869
3870         return ret;
3871 }
3872
3873 #endif /* CONFIG_P2P */