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