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