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