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