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