vendor/wpa_supplicant: upgrade from 2.1 to 2.9
[dragonfly.git] / contrib / wpa_supplicant / 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 "ap/sta_info.h"
17 #include "../config.h"
18 #include "../wpa_supplicant_i.h"
19 #include "../bss.h"
20 #include "../wpas_glue.h"
21 #include "dbus_new_helpers.h"
22 #include "dbus_dict_helpers.h"
23 #include "dbus_new.h"
24 #include "dbus_new_handlers.h"
25 #include "dbus_common_i.h"
26 #include "dbus_new_handlers_p2p.h"
27 #include "p2p/p2p.h"
28 #include "../p2p_supplicant.h"
29
30 #ifdef CONFIG_AP /* until needed by something else */
31
32 /*
33  * NameOwnerChanged handling
34  *
35  * Some services we provide allow an application to register for
36  * a signal that it needs. While it can also unregister, we must
37  * be prepared for the case where the application simply crashes
38  * and thus doesn't clean up properly. The way to handle this in
39  * DBus is to register for the NameOwnerChanged signal which will
40  * signal an owner change to NULL if the peer closes the socket
41  * for whatever reason.
42  *
43  * Handle this signal via a filter function whenever necessary.
44  * The code below also handles refcounting in case in the future
45  * there will be multiple instances of this subscription scheme.
46  */
47 static const char wpas_dbus_noc_filter_str[] =
48         "interface=org.freedesktop.DBus,member=NameOwnerChanged";
49
50
51 static DBusHandlerResult noc_filter(DBusConnection *conn,
52                                     DBusMessage *message, void *data)
53 {
54         struct wpas_dbus_priv *priv = data;
55
56         if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
57                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
58
59         if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
60                                    "NameOwnerChanged")) {
61                 const char *name;
62                 const char *prev_owner;
63                 const char *new_owner;
64                 DBusError derr;
65                 struct wpa_supplicant *wpa_s;
66
67                 dbus_error_init(&derr);
68
69                 if (!dbus_message_get_args(message, &derr,
70                                            DBUS_TYPE_STRING, &name,
71                                            DBUS_TYPE_STRING, &prev_owner,
72                                            DBUS_TYPE_STRING, &new_owner,
73                                            DBUS_TYPE_INVALID)) {
74                         /* Ignore this error */
75                         dbus_error_free(&derr);
76                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
77                 }
78
79                 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
80                         if (wpa_s->preq_notify_peer != NULL &&
81                             os_strcmp(name, wpa_s->preq_notify_peer) == 0 &&
82                             (new_owner == NULL || os_strlen(new_owner) == 0)) {
83                                 /* probe request owner disconnected */
84                                 os_free(wpa_s->preq_notify_peer);
85                                 wpa_s->preq_notify_peer = NULL;
86                                 wpas_dbus_unsubscribe_noc(priv);
87                         }
88                 }
89         }
90
91         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
92 }
93
94
95 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv)
96 {
97         priv->dbus_noc_refcnt++;
98         if (priv->dbus_noc_refcnt > 1)
99                 return;
100
101         if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) {
102                 wpa_printf(MSG_ERROR, "dbus: failed to add filter");
103                 return;
104         }
105
106         dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL);
107 }
108
109
110 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
111 {
112         priv->dbus_noc_refcnt--;
113         if (priv->dbus_noc_refcnt > 0)
114                 return;
115
116         dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL);
117         dbus_connection_remove_filter(priv->con, noc_filter, priv);
118 }
119
120 #endif /* CONFIG_AP */
121
122
123 /**
124  * wpas_dbus_signal_interface - Send a interface related event signal
125  * @wpa_s: %wpa_supplicant network interface data
126  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
127  * @properties: Whether to add second argument with object properties
128  *
129  * Notify listeners about event related with interface
130  */
131 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
132                                        const char *sig_name,
133                                        dbus_bool_t properties)
134 {
135         struct wpas_dbus_priv *iface;
136         DBusMessage *msg;
137         DBusMessageIter iter;
138
139         iface = wpa_s->global->dbus;
140
141         /* Do nothing if the control interface is not turned on */
142         if (iface == NULL || !wpa_s->dbus_new_path)
143                 return;
144
145         msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
146                                       WPAS_DBUS_NEW_INTERFACE, sig_name);
147         if (msg == NULL)
148                 return;
149
150         dbus_message_iter_init_append(msg, &iter);
151         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
152                                             &wpa_s->dbus_new_path) ||
153             (properties &&
154              !wpa_dbus_get_object_properties(
155                      iface, wpa_s->dbus_new_path,
156                      WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)))
157                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
158         else
159                 dbus_connection_send(iface->con, msg, NULL);
160         dbus_message_unref(msg);
161 }
162
163
164 /**
165  * wpas_dbus_signal_interface_added - Send a interface created signal
166  * @wpa_s: %wpa_supplicant network interface data
167  *
168  * Notify listeners about creating new interface
169  */
170 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
171 {
172         wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
173 }
174
175
176 /**
177  * wpas_dbus_signal_interface_removed - Send a interface removed signal
178  * @wpa_s: %wpa_supplicant network interface data
179  *
180  * Notify listeners about removing interface
181  */
182 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
183 {
184         wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
185
186 }
187
188
189 /**
190  * wpas_dbus_signal_scan_done - send scan done signal
191  * @wpa_s: %wpa_supplicant network interface data
192  * @success: indicates if scanning succeed or failed
193  *
194  * Notify listeners about finishing a scan
195  */
196 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
197 {
198         struct wpas_dbus_priv *iface;
199         DBusMessage *msg;
200         dbus_bool_t succ;
201
202         iface = wpa_s->global->dbus;
203
204         /* Do nothing if the control interface is not turned on */
205         if (iface == NULL || !wpa_s->dbus_new_path)
206                 return;
207
208         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
209                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
210                                       "ScanDone");
211         if (msg == NULL)
212                 return;
213
214         succ = success ? TRUE : FALSE;
215         if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
216                                      DBUS_TYPE_INVALID))
217                 dbus_connection_send(iface->con, msg, NULL);
218         else
219                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
220         dbus_message_unref(msg);
221 }
222
223
224 /**
225  * wpas_dbus_signal_bss - Send a BSS related event signal
226  * @wpa_s: %wpa_supplicant network interface data
227  * @bss_obj_path: BSS object path
228  * @sig_name: signal name - BSSAdded or BSSRemoved
229  * @properties: Whether to add second argument with object properties
230  *
231  * Notify listeners about event related with BSS
232  */
233 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
234                                  const char *bss_obj_path,
235                                  const char *sig_name, dbus_bool_t properties)
236 {
237         struct wpas_dbus_priv *iface;
238         DBusMessage *msg;
239         DBusMessageIter iter;
240
241         iface = wpa_s->global->dbus;
242
243         /* Do nothing if the control interface is not turned on */
244         if (iface == NULL || !wpa_s->dbus_new_path)
245                 return;
246
247         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
248                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
249                                       sig_name);
250         if (msg == NULL)
251                 return;
252
253         dbus_message_iter_init_append(msg, &iter);
254         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
255                                             &bss_obj_path) ||
256             (properties &&
257              !wpa_dbus_get_object_properties(iface, bss_obj_path,
258                                              WPAS_DBUS_NEW_IFACE_BSS,
259                                              &iter)))
260                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
261         else
262                 dbus_connection_send(iface->con, msg, NULL);
263         dbus_message_unref(msg);
264 }
265
266
267 /**
268  * wpas_dbus_signal_bss_added - Send a BSS added signal
269  * @wpa_s: %wpa_supplicant network interface data
270  * @bss_obj_path: new BSS object path
271  *
272  * Notify listeners about adding new BSS
273  */
274 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
275                                        const char *bss_obj_path)
276 {
277         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
278 }
279
280
281 /**
282  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
283  * @wpa_s: %wpa_supplicant network interface data
284  * @bss_obj_path: BSS object path
285  *
286  * Notify listeners about removing BSS
287  */
288 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
289                                          const char *bss_obj_path)
290 {
291         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
292 }
293
294
295 /**
296  * wpas_dbus_signal_blob - Send a blob related event signal
297  * @wpa_s: %wpa_supplicant network interface data
298  * @name: blob name
299  * @sig_name: signal name - BlobAdded or BlobRemoved
300  *
301  * Notify listeners about event related with blob
302  */
303 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
304                                   const char *name, const char *sig_name)
305 {
306         struct wpas_dbus_priv *iface;
307         DBusMessage *msg;
308
309         iface = wpa_s->global->dbus;
310
311         /* Do nothing if the control interface is not turned on */
312         if (iface == NULL || !wpa_s->dbus_new_path)
313                 return;
314
315         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
316                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
317                                       sig_name);
318         if (msg == NULL)
319                 return;
320
321         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
322                                      DBUS_TYPE_INVALID))
323                 dbus_connection_send(iface->con, msg, NULL);
324         else
325                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
326         dbus_message_unref(msg);
327 }
328
329
330 /**
331  * wpas_dbus_signal_blob_added - Send a blob added signal
332  * @wpa_s: %wpa_supplicant network interface data
333  * @name: blob name
334  *
335  * Notify listeners about adding a new blob
336  */
337 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
338                                  const char *name)
339 {
340         wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
341 }
342
343
344 /**
345  * wpas_dbus_signal_blob_removed - Send a blob removed signal
346  * @wpa_s: %wpa_supplicant network interface data
347  * @name: blob name
348  *
349  * Notify listeners about removing blob
350  */
351 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
352                                    const char *name)
353 {
354         wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
355 }
356
357
358 /**
359  * wpas_dbus_signal_network - Send a network related event signal
360  * @wpa_s: %wpa_supplicant network interface data
361  * @id: new network id
362  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
363  * @properties: determines if add second argument with object properties
364  *
365  * Notify listeners about event related with configured network
366  */
367 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
368                                      int id, const char *sig_name,
369                                      dbus_bool_t properties)
370 {
371         struct wpas_dbus_priv *iface;
372         DBusMessage *msg;
373         DBusMessageIter iter;
374         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
375
376         iface = wpa_s->global->dbus;
377
378         /* Do nothing if the control interface is not turned on */
379         if (iface == NULL || !wpa_s->dbus_new_path)
380                 return;
381
382         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
383                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
384                     wpa_s->dbus_new_path, id);
385
386         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
387                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
388                                       sig_name);
389         if (msg == NULL)
390                 return;
391
392         dbus_message_iter_init_append(msg, &iter);
393         path = net_obj_path;
394         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
395                                             &path) ||
396             (properties &&
397              !wpa_dbus_get_object_properties(
398                      iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
399                      &iter)))
400                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
401         else
402                 dbus_connection_send(iface->con, msg, NULL);
403         dbus_message_unref(msg);
404 }
405
406
407 /**
408  * wpas_dbus_signal_network_added - Send a network added signal
409  * @wpa_s: %wpa_supplicant network interface data
410  * @id: new network id
411  *
412  * Notify listeners about adding new network
413  */
414 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
415                                            int id)
416 {
417         wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
418 }
419
420
421 /**
422  * wpas_dbus_signal_network_removed - Send a network removed signal
423  * @wpa_s: %wpa_supplicant network interface data
424  * @id: network id
425  *
426  * Notify listeners about removing a network
427  */
428 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
429                                              int id)
430 {
431         wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
432 }
433
434
435 /**
436  * wpas_dbus_signal_network_selected - Send a network selected signal
437  * @wpa_s: %wpa_supplicant network interface data
438  * @id: network id
439  *
440  * Notify listeners about selecting a network
441  */
442 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
443 {
444         wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
445 }
446
447
448 /**
449  * wpas_dbus_signal_network_request - Indicate that additional information
450  * (EAP password, etc.) is required to complete the association to this SSID
451  * @wpa_s: %wpa_supplicant network interface data
452  * @rtype: The specific additional information required
453  * @default_text: Optional description of required information
454  *
455  * Request additional information or passwords to complete an association
456  * request.
457  */
458 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
459                                       struct wpa_ssid *ssid,
460                                       enum wpa_ctrl_req_type rtype,
461                                       const char *default_txt)
462 {
463         struct wpas_dbus_priv *iface;
464         DBusMessage *msg;
465         DBusMessageIter iter;
466         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
467         const char *field, *txt = NULL, *net_ptr;
468
469         iface = wpa_s->global->dbus;
470
471         /* Do nothing if the control interface is not turned on */
472         if (iface == NULL || !wpa_s->dbus_new_path)
473                 return;
474
475         field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
476         if (field == NULL)
477                 return;
478
479         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
480                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
481                                       "NetworkRequest");
482         if (msg == NULL)
483                 return;
484
485         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
486                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
487                     wpa_s->dbus_new_path, ssid->id);
488         net_ptr = &net_obj_path[0];
489
490         dbus_message_iter_init_append(msg, &iter);
491         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
492                                             &net_ptr) ||
493             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) ||
494             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
495                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
496         else
497                 dbus_connection_send(iface->con, msg, NULL);
498         dbus_message_unref(msg);
499 }
500
501
502 /**
503  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
504  * @wpa_s: %wpa_supplicant network interface data
505  * @ssid: configured network which Enabled property has changed
506  *
507  * Sends PropertyChanged signals containing new value of Enabled property
508  * for specified network
509  */
510 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
511                                               struct wpa_ssid *ssid)
512 {
513
514         char path[WPAS_DBUS_OBJECT_PATH_MAX];
515
516         if (!wpa_s->dbus_new_path)
517                 return;
518         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
519                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
520                     wpa_s->dbus_new_path, ssid->id);
521
522         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
523                                        WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
524 }
525
526
527 #ifdef CONFIG_WPS
528
529 /**
530  * wpas_dbus_signal_wps_event_pbc_overlap - Signals PBC overlap WPS event
531  * @wpa_s: %wpa_supplicant network interface data
532  *
533  * Sends Event dbus signal with name "pbc-overlap" and empty dict as arguments
534  */
535 void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
536 {
537
538         DBusMessage *msg;
539         DBusMessageIter iter, dict_iter;
540         struct wpas_dbus_priv *iface;
541         char *key = "pbc-overlap";
542
543         iface = wpa_s->global->dbus;
544
545         /* Do nothing if the control interface is not turned on */
546         if (iface == NULL || !wpa_s->dbus_new_path)
547                 return;
548
549         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
550                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
551         if (msg == NULL)
552                 return;
553
554         dbus_message_iter_init_append(msg, &iter);
555
556         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
557             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
558             !wpa_dbus_dict_close_write(&iter, &dict_iter))
559                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
560         else
561                 dbus_connection_send(iface->con, msg, NULL);
562
563         dbus_message_unref(msg);
564 }
565
566
567 /**
568  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
569  * @wpa_s: %wpa_supplicant network interface data
570  *
571  * Sends Event dbus signal with name "success" and empty dict as arguments
572  */
573 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
574 {
575
576         DBusMessage *msg;
577         DBusMessageIter iter, dict_iter;
578         struct wpas_dbus_priv *iface;
579         char *key = "success";
580
581         iface = wpa_s->global->dbus;
582
583         /* Do nothing if the control interface is not turned on */
584         if (iface == NULL || !wpa_s->dbus_new_path)
585                 return;
586
587         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
589         if (msg == NULL)
590                 return;
591
592         dbus_message_iter_init_append(msg, &iter);
593
594         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
595             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
596             !wpa_dbus_dict_close_write(&iter, &dict_iter))
597                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
598         else
599                 dbus_connection_send(iface->con, msg, NULL);
600
601         dbus_message_unref(msg);
602 }
603
604
605 /**
606  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
607  * @wpa_s: %wpa_supplicant network interface data
608  * @fail: WPS failure information
609  *
610  * Sends Event dbus signal with name "fail" and dictionary containing
611  * "msg field with fail message number (int32) as arguments
612  */
613 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
614                                      struct wps_event_fail *fail)
615 {
616
617         DBusMessage *msg;
618         DBusMessageIter iter, dict_iter;
619         struct wpas_dbus_priv *iface;
620         char *key = "fail";
621
622         iface = wpa_s->global->dbus;
623
624         /* Do nothing if the control interface is not turned on */
625         if (iface == NULL || !wpa_s->dbus_new_path)
626                 return;
627
628         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
629                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
630         if (msg == NULL)
631                 return;
632
633         dbus_message_iter_init_append(msg, &iter);
634
635         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
636             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
637             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
638             !wpa_dbus_dict_append_int32(&dict_iter, "config_error",
639                                         fail->config_error) ||
640             !wpa_dbus_dict_append_int32(&dict_iter, "error_indication",
641                                         fail->error_indication) ||
642             !wpa_dbus_dict_close_write(&iter, &dict_iter))
643                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
644         else
645                 dbus_connection_send(iface->con, msg, NULL);
646
647         dbus_message_unref(msg);
648 }
649
650
651 /**
652  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
653  * @wpa_s: %wpa_supplicant network interface data
654  * @m2d: M2D event data information
655  *
656  * Sends Event dbus signal with name "m2d" and dictionary containing
657  * fields of wps_event_m2d structure.
658  */
659 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660                                     struct wps_event_m2d *m2d)
661 {
662
663         DBusMessage *msg;
664         DBusMessageIter iter, dict_iter;
665         struct wpas_dbus_priv *iface;
666         char *key = "m2d";
667
668         iface = wpa_s->global->dbus;
669
670         /* Do nothing if the control interface is not turned on */
671         if (iface == NULL || !wpa_s->dbus_new_path)
672                 return;
673
674         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
675                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
676         if (msg == NULL)
677                 return;
678
679         dbus_message_iter_init_append(msg, &iter);
680
681         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
682             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
683             !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
684                                          m2d->config_methods) ||
685             !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
686                                              (const char *) m2d->manufacturer,
687                                              m2d->manufacturer_len) ||
688             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
689                                              (const char *) m2d->model_name,
690                                              m2d->model_name_len) ||
691             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
692                                              (const char *) m2d->model_number,
693                                              m2d->model_number_len) ||
694             !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
695                                              (const char *)
696                                              m2d->serial_number,
697                                              m2d->serial_number_len) ||
698             !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
699                                              (const char *) m2d->dev_name,
700                                              m2d->dev_name_len) ||
701             !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
702                                              (const char *)
703                                              m2d->primary_dev_type, 8) ||
704             !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
705                                          m2d->config_error) ||
706             !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
707                                          m2d->dev_password_id) ||
708             !wpa_dbus_dict_close_write(&iter, &dict_iter))
709                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
710         else
711                 dbus_connection_send(iface->con, msg, NULL);
712
713         dbus_message_unref(msg);
714 }
715
716
717 /**
718  * wpas_dbus_signal_wps_cred - Signals new credentials
719  * @wpa_s: %wpa_supplicant network interface data
720  * @cred: WPS Credential information
721  *
722  * Sends signal with credentials in directory argument
723  */
724 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
725                                const struct wps_credential *cred)
726 {
727         DBusMessage *msg;
728         DBusMessageIter iter, dict_iter;
729         struct wpas_dbus_priv *iface;
730         char *auth_type[5]; /* we have five possible authentication types */
731         int at_num = 0;
732         char *encr_type[3]; /* we have three possible encryption types */
733         int et_num = 0;
734
735         iface = wpa_s->global->dbus;
736
737         /* Do nothing if the control interface is not turned on */
738         if (iface == NULL || !wpa_s->dbus_new_path)
739                 return;
740
741         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
742                                       WPAS_DBUS_NEW_IFACE_WPS,
743                                       "Credentials");
744         if (msg == NULL)
745                 return;
746
747         dbus_message_iter_init_append(msg, &iter);
748         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
749                 goto nomem;
750
751         if (cred->auth_type & WPS_AUTH_OPEN)
752                 auth_type[at_num++] = "open";
753         if (cred->auth_type & WPS_AUTH_WPAPSK)
754                 auth_type[at_num++] = "wpa-psk";
755         if (cred->auth_type & WPS_AUTH_WPA)
756                 auth_type[at_num++] = "wpa-eap";
757         if (cred->auth_type & WPS_AUTH_WPA2)
758                 auth_type[at_num++] = "wpa2-eap";
759         if (cred->auth_type & WPS_AUTH_WPA2PSK)
760                 auth_type[at_num++] = "wpa2-psk";
761
762         if (cred->encr_type & WPS_ENCR_NONE)
763                 encr_type[et_num++] = "none";
764         if (cred->encr_type & WPS_ENCR_TKIP)
765                 encr_type[et_num++] = "tkip";
766         if (cred->encr_type & WPS_ENCR_AES)
767                 encr_type[et_num++] = "aes";
768
769         if ((wpa_s->current_ssid &&
770              !wpa_dbus_dict_append_byte_array(
771                      &dict_iter, "BSSID",
772                      (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
773             !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
774                                              (const char *) cred->ssid,
775                                              cred->ssid_len) ||
776             !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
777                                                (const char **) auth_type,
778                                                at_num) ||
779             !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
780                                                (const char **) encr_type,
781                                                et_num) ||
782             !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
783                                              (const char *) cred->key,
784                                              cred->key_len) ||
785             !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
786                                          cred->key_idx) ||
787             !wpa_dbus_dict_close_write(&iter, &dict_iter))
788                 goto nomem;
789
790         dbus_connection_send(iface->con, msg, NULL);
791
792 nomem:
793         dbus_message_unref(msg);
794 }
795
796 #endif /* CONFIG_WPS */
797
798
799 #ifdef CONFIG_MESH
800
801 void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
802                                          struct wpa_ssid *ssid)
803 {
804         struct wpas_dbus_priv *iface;
805         DBusMessage *msg;
806         DBusMessageIter iter, dict_iter;
807
808         iface = wpa_s->global->dbus;
809
810         /* Do nothing if the control interface is not turned on */
811         if (!iface || !wpa_s->dbus_new_path)
812                 return;
813
814         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
815                                       WPAS_DBUS_NEW_IFACE_MESH,
816                                       "MeshGroupStarted");
817         if (!msg)
818                 return;
819
820         dbus_message_iter_init_append(msg, &iter);
821         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
822             !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
823                                              (const char *) ssid->ssid,
824                                              ssid->ssid_len) ||
825             !wpa_dbus_dict_close_write(&iter, &dict_iter))
826                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
827         else
828                 dbus_connection_send(iface->con, msg, NULL);
829         dbus_message_unref(msg);
830 }
831
832
833 void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
834                                          const u8 *meshid, u8 meshid_len,
835                                          int reason)
836 {
837         struct wpas_dbus_priv *iface;
838         DBusMessage *msg;
839         DBusMessageIter iter, dict_iter;
840
841         iface = wpa_s->global->dbus;
842
843         /* Do nothing if the control interface is not turned on */
844         if (!iface || !wpa_s->dbus_new_path)
845                 return;
846
847         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
848                                       WPAS_DBUS_NEW_IFACE_MESH,
849                                       "MeshGroupRemoved");
850         if (!msg)
851                 return;
852
853         dbus_message_iter_init_append(msg, &iter);
854         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
855             !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
856                                              (const char *) meshid,
857                                              meshid_len) ||
858             !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
859                                         reason) ||
860             !wpa_dbus_dict_close_write(&iter, &dict_iter))
861                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
862         else
863                 dbus_connection_send(iface->con, msg, NULL);
864         dbus_message_unref(msg);
865 }
866
867
868 void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
869                                           const u8 *peer_addr)
870 {
871         struct wpas_dbus_priv *iface;
872         DBusMessage *msg;
873         DBusMessageIter iter, dict_iter;
874
875         iface = wpa_s->global->dbus;
876
877         /* Do nothing if the control interface is not turned on */
878         if (!iface || !wpa_s->dbus_new_path)
879                 return;
880
881         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
882                                       WPAS_DBUS_NEW_IFACE_MESH,
883                                       "MeshPeerConnected");
884         if (!msg)
885                 return;
886
887         dbus_message_iter_init_append(msg, &iter);
888         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
889             !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
890                                              (const char *) peer_addr,
891                                              ETH_ALEN) ||
892             !wpa_dbus_dict_close_write(&iter, &dict_iter))
893                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
894         else
895                 dbus_connection_send(iface->con, msg, NULL);
896         dbus_message_unref(msg);
897 }
898
899
900 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
901                                              const u8 *peer_addr, int reason)
902 {
903         struct wpas_dbus_priv *iface;
904         DBusMessage *msg;
905         DBusMessageIter iter, dict_iter;
906
907         iface = wpa_s->global->dbus;
908
909         /* Do nothing if the control interface is not turned on */
910         if (!iface || !wpa_s->dbus_new_path)
911                 return;
912
913         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
914                                       WPAS_DBUS_NEW_IFACE_MESH,
915                                       "MeshPeerDisconnected");
916         if (!msg)
917                 return;
918
919         dbus_message_iter_init_append(msg, &iter);
920         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
921             !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
922                                              (const char *) peer_addr,
923                                              ETH_ALEN) ||
924             !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
925                                         reason) ||
926             !wpa_dbus_dict_close_write(&iter, &dict_iter))
927                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
928         else
929                 dbus_connection_send(iface->con, msg, NULL);
930         dbus_message_unref(msg);
931 }
932
933 #endif /* CONFIG_MESH */
934
935
936 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
937                                     int depth, const char *subject,
938                                     const char *altsubject[],
939                                     int num_altsubject,
940                                     const char *cert_hash,
941                                     const struct wpabuf *cert)
942 {
943         struct wpas_dbus_priv *iface;
944         DBusMessage *msg;
945         DBusMessageIter iter, dict_iter;
946
947         iface = wpa_s->global->dbus;
948
949         /* Do nothing if the control interface is not turned on */
950         if (iface == NULL || !wpa_s->dbus_new_path)
951                 return;
952
953         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
954                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
955                                       "Certification");
956         if (msg == NULL)
957                 return;
958
959         dbus_message_iter_init_append(msg, &iter);
960         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
961             !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
962             !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
963             (altsubject && num_altsubject &&
964              !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
965                                                 altsubject, num_altsubject)) ||
966             (cert_hash &&
967              !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
968                                           cert_hash)) ||
969             (cert &&
970              !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
971                                               wpabuf_head(cert),
972                                               wpabuf_len(cert))) ||
973             !wpa_dbus_dict_close_write(&iter, &dict_iter))
974                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
975         else
976                 dbus_connection_send(iface->con, msg, NULL);
977         dbus_message_unref(msg);
978 }
979
980
981 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
982                                  const char *status, const char *parameter)
983 {
984         struct wpas_dbus_priv *iface;
985         DBusMessage *msg;
986         DBusMessageIter iter;
987
988         iface = wpa_s->global->dbus;
989
990         /* Do nothing if the control interface is not turned on */
991         if (iface == NULL || !wpa_s->dbus_new_path)
992                 return;
993
994         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
995                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
996                                       "EAP");
997         if (msg == NULL)
998                 return;
999
1000         dbus_message_iter_init_append(msg, &iter);
1001
1002         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
1003             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1004                                             &parameter))
1005                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1006         else
1007                 dbus_connection_send(iface->con, msg, NULL);
1008         dbus_message_unref(msg);
1009 }
1010
1011
1012 /**
1013  * wpas_dbus_signal_sta - Send a station related event signal
1014  * @wpa_s: %wpa_supplicant network interface data
1015  * @sta: station mac address
1016  * @sig_name: signal name - StaAuthorized or StaDeauthorized
1017  *
1018  * Notify listeners about event related with station
1019  */
1020 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
1021                                  const u8 *sta, const char *sig_name)
1022 {
1023         struct wpas_dbus_priv *iface;
1024         DBusMessage *msg;
1025         char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
1026         char *dev_mac;
1027
1028         os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
1029         dev_mac = sta_mac;
1030
1031         iface = wpa_s->global->dbus;
1032
1033         /* Do nothing if the control interface is not turned on */
1034         if (iface == NULL || !wpa_s->dbus_new_path)
1035                 return;
1036
1037         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1038                                       WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1039         if (msg == NULL)
1040                 return;
1041
1042         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
1043                                      DBUS_TYPE_INVALID))
1044                 dbus_connection_send(iface->con, msg, NULL);
1045         else
1046                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1047         dbus_message_unref(msg);
1048
1049         wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
1050                    sta_mac, sig_name);
1051 }
1052
1053
1054 /**
1055  * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
1056  * @wpa_s: %wpa_supplicant network interface data
1057  * @sta: station mac address
1058  *
1059  * Notify listeners a new station has been authorized
1060  */
1061 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
1062                                      const u8 *sta)
1063 {
1064         wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
1065 }
1066
1067
1068 /**
1069  * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
1070  * @wpa_s: %wpa_supplicant network interface data
1071  * @sta: station mac address
1072  *
1073  * Notify listeners a station has been deauthorized
1074  */
1075 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
1076                                        const u8 *sta)
1077 {
1078         wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
1079 }
1080
1081
1082 /**
1083  * wpas_dbus_signal_station - Send an event signal related to a station object
1084  * @wpa_s: %wpa_supplicant network interface data
1085  * @station_obj_path: Station object path
1086  * @sig_name: signal name - StationAdded or StationRemoved
1087  * @properties: Whether to add second argument with object properties
1088  *
1089  * Notify listeners about event related with station.
1090  */
1091 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
1092                                      const char *station_obj_path,
1093                                      const char *sig_name,
1094                                      dbus_bool_t properties)
1095 {
1096         struct wpas_dbus_priv *iface;
1097         DBusMessage *msg;
1098         DBusMessageIter iter;
1099
1100         iface = wpa_s->global->dbus;
1101
1102         /* Do nothing if the control interface is not turned on */
1103         if (!iface || !wpa_s->dbus_new_path)
1104                 return;
1105
1106         wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
1107         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1108                                       WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1109         if (!msg)
1110                 return;
1111
1112         dbus_message_iter_init_append(msg, &iter);
1113         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1114                                             &station_obj_path) ||
1115             (properties &&
1116              !wpa_dbus_get_object_properties(iface, station_obj_path,
1117                                              WPAS_DBUS_NEW_IFACE_STA,
1118                                              &iter)))
1119                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1120         else
1121                 dbus_connection_send(iface->con, msg, NULL);
1122         dbus_message_unref(msg);
1123 }
1124
1125
1126 /**
1127  * wpas_dbus_signal_station_added - Send a Station added signal
1128  * @wpa_s: %wpa_supplicant network interface data
1129  * @station_obj_path: new Station object path
1130  *
1131  * Notify listeners about adding new Station
1132  */
1133 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
1134                                            const char *station_obj_path)
1135 {
1136         wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
1137 }
1138
1139
1140 /**
1141  * wpas_dbus_signal_station_removed - Send a Station removed signal
1142  * @wpa_s: %wpa_supplicant network interface data
1143  * @station_obj_path: Station object path
1144  *
1145  * Notify listeners about removing Station
1146  */
1147 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
1148                                              const char *station_obj_path)
1149 {
1150         wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
1151                                  FALSE);
1152 }
1153
1154
1155 #ifdef CONFIG_P2P
1156
1157 /**
1158  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
1159  * @wpa_s: %wpa_supplicant network interface data
1160  * @role: role of this device (client or GO)
1161  * Sends signal with i/f name and role as string arguments
1162  */
1163 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
1164                                         const char *role)
1165 {
1166         DBusMessage *msg;
1167         DBusMessageIter iter, dict_iter;
1168         struct wpas_dbus_priv *iface = wpa_s->global->dbus;
1169         struct wpa_supplicant *parent;
1170
1171         /* Do nothing if the control interface is not turned on */
1172         if (iface == NULL)
1173                 return;
1174
1175         parent = wpa_s->parent;
1176         if (parent->p2p_mgmt)
1177                 parent = parent->parent;
1178
1179         if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
1180             !parent->dbus_new_path)
1181                 return;
1182
1183         msg = dbus_message_new_signal(parent->dbus_new_path,
1184                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1185                                       "GroupFinished");
1186         if (msg == NULL)
1187                 return;
1188
1189         dbus_message_iter_init_append(msg, &iter);
1190         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1191             !wpa_dbus_dict_append_object_path(&dict_iter,
1192                                               "interface_object",
1193                                               wpa_s->dbus_new_path) ||
1194             !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
1195             !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1196                                               wpa_s->dbus_groupobj_path) ||
1197             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1198                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1199         else
1200                 dbus_connection_send(iface->con, msg, NULL);
1201         dbus_message_unref(msg);
1202 }
1203
1204
1205 /**
1206  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
1207  *
1208  * @dev_addr - who sent the request or responded to our request.
1209  * @request - Will be 1 if request, 0 for response.
1210  * @status - valid only in case of response
1211  * @config_methods - wps config methods
1212  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
1213  *
1214  * Sends following provision discovery related events:
1215  *      ProvisionDiscoveryRequestDisplayPin
1216  *      ProvisionDiscoveryResponseDisplayPin
1217  *      ProvisionDiscoveryRequestEnterPin
1218  *      ProvisionDiscoveryResponseEnterPin
1219  *      ProvisionDiscoveryPBCRequest
1220  *      ProvisionDiscoveryPBCResponse
1221  *
1222  *      TODO::
1223  *      ProvisionDiscoveryFailure (timeout case)
1224  */
1225 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
1226                                               const u8 *dev_addr, int request,
1227                                               enum p2p_prov_disc_status status,
1228                                               u16 config_methods,
1229                                               unsigned int generated_pin)
1230 {
1231         DBusMessage *msg;
1232         DBusMessageIter iter;
1233         struct wpas_dbus_priv *iface;
1234         char *_signal;
1235         int add_pin = 0;
1236         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1237         int error_ret = 1;
1238         char pin[9], *p_pin = NULL;
1239
1240         iface = wpa_s->global->dbus;
1241
1242         /* Do nothing if the control interface is not turned on */
1243         if (iface == NULL)
1244                 return;
1245
1246         if (wpa_s->p2p_mgmt)
1247                 wpa_s = wpa_s->parent;
1248         if (!wpa_s->dbus_new_path)
1249                 return;
1250
1251         if (request || !status) {
1252                 if (config_methods & WPS_CONFIG_DISPLAY)
1253                         _signal = request ?
1254                                  "ProvisionDiscoveryRequestDisplayPin" :
1255                                  "ProvisionDiscoveryResponseEnterPin";
1256                 else if (config_methods & WPS_CONFIG_KEYPAD)
1257                         _signal = request ?
1258                                  "ProvisionDiscoveryRequestEnterPin" :
1259                                  "ProvisionDiscoveryResponseDisplayPin";
1260                 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
1261                         _signal = request ? "ProvisionDiscoveryPBCRequest" :
1262                                    "ProvisionDiscoveryPBCResponse";
1263                 else
1264                         return; /* Unknown or un-supported method */
1265         } else {
1266                 /* Explicit check for failure response */
1267                 _signal = "ProvisionDiscoveryFailure";
1268         }
1269
1270         add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
1271                    (!request && !status &&
1272                         (config_methods & WPS_CONFIG_KEYPAD)));
1273
1274         if (add_pin) {
1275                 os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
1276                 p_pin = pin;
1277         }
1278
1279         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1280                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
1281         if (msg == NULL)
1282                 return;
1283
1284         /* Check if this is a known peer */
1285         if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
1286                 goto error;
1287
1288         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1289                         "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1290                         COMPACT_MACSTR,
1291                         wpa_s->dbus_new_path, MAC2STR(dev_addr));
1292
1293         path = peer_obj_path;
1294
1295         dbus_message_iter_init_append(msg, &iter);
1296
1297         if (!dbus_message_iter_append_basic(&iter,
1298                                             DBUS_TYPE_OBJECT_PATH,
1299                                             &path))
1300                         goto error;
1301
1302         if (!request && status)
1303                 /* Attach status to ProvisionDiscoveryFailure */
1304                 error_ret = !dbus_message_iter_append_basic(&iter,
1305                                                     DBUS_TYPE_INT32,
1306                                                     &status);
1307         else
1308                 error_ret = (add_pin &&
1309                                  !dbus_message_iter_append_basic(&iter,
1310                                                         DBUS_TYPE_STRING,
1311                                                         &p_pin));
1312
1313 error:
1314         if (!error_ret)
1315                 dbus_connection_send(iface->con, msg, NULL);
1316         else
1317                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1318
1319         dbus_message_unref(msg);
1320 }
1321
1322
1323 /**
1324  * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
1325  * @wpa_s: %wpa_supplicant network interface data
1326  * @src: Source address of the message triggering this notification
1327  * @dev_passwd_id: WPS Device Password Id
1328  * @go_intent: Peer's GO Intent value
1329  *
1330  * Sends signal to notify that a peer P2P Device is requesting group owner
1331  * negotiation with us.
1332  */
1333 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1334                                      const u8 *src, u16 dev_passwd_id,
1335                                      u8 go_intent)
1336 {
1337         DBusMessage *msg;
1338         DBusMessageIter iter;
1339         struct wpas_dbus_priv *iface;
1340         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1341
1342         iface = wpa_s->global->dbus;
1343
1344         /* Do nothing if the control interface is not turned on */
1345         if (iface == NULL)
1346                 return;
1347
1348         if (wpa_s->p2p_mgmt)
1349                 wpa_s = wpa_s->parent;
1350         if (!wpa_s->dbus_new_path)
1351                 return;
1352
1353         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1354                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1355                     wpa_s->dbus_new_path, MAC2STR(src));
1356         path = peer_obj_path;
1357
1358         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1359                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1360                                       "GONegotiationRequest");
1361         if (msg == NULL)
1362                 return;
1363
1364         dbus_message_iter_init_append(msg, &iter);
1365
1366         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1367                                             &path) ||
1368             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1369                                             &dev_passwd_id) ||
1370             !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
1371                                             &go_intent))
1372                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1373         else
1374                 dbus_connection_send(iface->con, msg, NULL);
1375
1376         dbus_message_unref(msg);
1377 }
1378
1379
1380 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1381                                         const struct wpa_ssid *ssid,
1382                                         char *group_obj_path)
1383 {
1384         char group_name[3];
1385
1386         if (!wpa_s->dbus_new_path ||
1387             os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1388                 return -1;
1389
1390         os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1391         group_name[2] = '\0';
1392
1393         os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1394                     "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1395                     wpa_s->dbus_new_path, group_name);
1396
1397         return 0;
1398 }
1399
1400
1401 struct group_changed_data {
1402         struct wpa_supplicant *wpa_s;
1403         struct p2p_peer_info *info;
1404 };
1405
1406
1407 static int match_group_where_peer_is_client(struct p2p_group *group,
1408                                             void *user_data)
1409 {
1410         struct group_changed_data *data = user_data;
1411         const struct p2p_group_config *cfg;
1412         struct wpa_supplicant *wpa_s_go;
1413
1414         if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1415                 return 1;
1416
1417         cfg = p2p_group_get_config(group);
1418
1419         wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1420                                          cfg->ssid_len);
1421         if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1422                 wpas_dbus_signal_peer_groups_changed(
1423                         data->wpa_s->p2pdev, data->info->p2p_device_addr);
1424                 return 0;
1425         }
1426
1427         return 1;
1428 }
1429
1430
1431 static void signal_peer_groups_changed(struct p2p_peer_info *info,
1432                                        void *user_data)
1433 {
1434         struct group_changed_data *data = user_data;
1435         struct wpa_supplicant *wpa_s_go;
1436
1437         wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
1438                                              info->p2p_device_addr);
1439         if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1440                 wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
1441                                                      info->p2p_device_addr);
1442                 return;
1443         }
1444
1445         data->info = info;
1446         p2p_loop_on_all_groups(data->wpa_s->global->p2p,
1447                                match_group_where_peer_is_client, data);
1448         data->info = NULL;
1449 }
1450
1451
1452 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
1453 {
1454         struct group_changed_data data;
1455
1456         os_memset(&data, 0, sizeof(data));
1457         data.wpa_s = wpa_s;
1458
1459         p2p_loop_on_known_peers(wpa_s->global->p2p,
1460                                 signal_peer_groups_changed, &data);
1461 }
1462
1463
1464 /**
1465  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1466  * started. Emitted when a group is successfully started
1467  * irrespective of the role (client/GO) of the current device
1468  *
1469  * @wpa_s: %wpa_supplicant network interface data
1470  * @client: this device is P2P client
1471  * @persistent: 0 - non persistent group, 1 - persistent group
1472  * @ip: When group role is client, it contains local IP address, netmask, and
1473  *      GO's IP address, if assigned; otherwise, NULL
1474  */
1475 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1476                                         int client, int persistent,
1477                                         const u8 *ip)
1478 {
1479         DBusMessage *msg;
1480         DBusMessageIter iter, dict_iter;
1481         struct wpas_dbus_priv *iface;
1482         struct wpa_supplicant *parent;
1483
1484         parent = wpa_s->parent;
1485         if (parent->p2p_mgmt)
1486                 parent = parent->parent;
1487
1488         iface = parent->global->dbus;
1489
1490         /* Do nothing if the control interface is not turned on */
1491         if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
1492                 return;
1493
1494         if (wpa_s->dbus_groupobj_path == NULL)
1495                 return;
1496
1497         /* New interface has been created for this group */
1498         msg = dbus_message_new_signal(parent->dbus_new_path,
1499                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1500                                       "GroupStarted");
1501         if (msg == NULL)
1502                 return;
1503
1504         dbus_message_iter_init_append(msg, &iter);
1505         /*
1506          * In case the device supports creating a separate interface the
1507          * DBus client will need to know the object path for the interface
1508          * object this group was created on, so include it here.
1509          */
1510         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1511             !wpa_dbus_dict_append_object_path(&dict_iter,
1512                                               "interface_object",
1513                                               wpa_s->dbus_new_path) ||
1514             !wpa_dbus_dict_append_string(&dict_iter, "role",
1515                                          client ? "client" : "GO") ||
1516             !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
1517             !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1518                                               wpa_s->dbus_groupobj_path) ||
1519             (ip &&
1520              (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1521                                                (char *) ip, 4) ||
1522               !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1523                                                (char *) ip + 4, 4) ||
1524               !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1525                                                (char *) ip + 8, 4))) ||
1526             !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1527                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1528         } else {
1529                 dbus_connection_send(iface->con, msg, NULL);
1530                 if (client)
1531                         peer_groups_changed(wpa_s);
1532         }
1533         dbus_message_unref(msg);
1534 }
1535
1536
1537 /**
1538  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1539  * @wpa_s: %wpa_supplicant network interface data
1540  * @res: Result of the GO Neg Request
1541  */
1542 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1543                                       struct p2p_go_neg_results *res)
1544 {
1545         DBusMessage *msg;
1546         DBusMessageIter iter, dict_iter;
1547         DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1548         struct wpas_dbus_priv *iface;
1549         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1550         dbus_int32_t freqs[P2P_MAX_CHANNELS];
1551         dbus_int32_t *f_array = freqs;
1552
1553
1554         iface = wpa_s->global->dbus;
1555
1556         if (wpa_s->p2p_mgmt)
1557                 wpa_s = wpa_s->parent;
1558
1559         os_memset(freqs, 0, sizeof(freqs));
1560         /* Do nothing if the control interface is not turned on */
1561         if (iface == NULL || !wpa_s->dbus_new_path)
1562                 return;
1563
1564         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1565                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1566                     wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1567         path = peer_obj_path;
1568
1569         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1570                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1571                                       res->status ? "GONegotiationFailure" :
1572                                                     "GONegotiationSuccess");
1573         if (msg == NULL)
1574                 return;
1575
1576         dbus_message_iter_init_append(msg, &iter);
1577         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1578             !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1579                                               path) ||
1580             !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1581                 goto err;
1582
1583         if (!res->status) {
1584                 int i = 0;
1585                 int freq_list_num = 0;
1586
1587                 if ((res->role_go &&
1588                      !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1589                                                   res->passphrase)) ||
1590                     !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1591                                                  res->role_go ? "GO" :
1592                                                  "client") ||
1593                     !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1594                                                 res->freq) ||
1595                     !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1596                                                      (const char *) res->ssid,
1597                                                      res->ssid_len) ||
1598                     !wpa_dbus_dict_append_byte_array(&dict_iter,
1599                                                      "peer_device_addr",
1600                                                      (const char *)
1601                                                      res->peer_device_addr,
1602                                                      ETH_ALEN) ||
1603                     !wpa_dbus_dict_append_byte_array(&dict_iter,
1604                                                      "peer_interface_addr",
1605                                                      (const char *)
1606                                                      res->peer_interface_addr,
1607                                                      ETH_ALEN) ||
1608                     !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1609                                                  p2p_wps_method_text(
1610                                                          res->wps_method)))
1611                         goto err;
1612
1613                 for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1614                         if (res->freq_list[i]) {
1615                                 freqs[i] = res->freq_list[i];
1616                                 freq_list_num++;
1617                         }
1618                 }
1619
1620                 if (!wpa_dbus_dict_begin_array(&dict_iter,
1621                                                "frequency_list",
1622                                                DBUS_TYPE_INT32_AS_STRING,
1623                                                &iter_dict_entry,
1624                                                &iter_dict_val,
1625                                                &iter_dict_array) ||
1626                     !dbus_message_iter_append_fixed_array(&iter_dict_array,
1627                                                           DBUS_TYPE_INT32,
1628                                                           &f_array,
1629                                                           freq_list_num) ||
1630                     !wpa_dbus_dict_end_array(&dict_iter,
1631                                              &iter_dict_entry,
1632                                              &iter_dict_val,
1633                                              &iter_dict_array) ||
1634                     !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1635                                                 res->persistent_group) ||
1636                     !wpa_dbus_dict_append_uint32(&dict_iter,
1637                                                  "peer_config_timeout",
1638                                                  res->peer_config_timeout))
1639                         goto err;
1640         }
1641
1642         if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1643                 goto err;
1644
1645         dbus_connection_send(iface->con, msg, NULL);
1646 err:
1647         dbus_message_unref(msg);
1648 }
1649
1650
1651 /**
1652  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1653  * @wpa_s: %wpa_supplicant network interface data
1654  * @status: Status of invitation process
1655  * @bssid: Basic Service Set Identifier
1656  */
1657 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1658                                             int status, const u8 *bssid)
1659 {
1660         DBusMessage *msg;
1661         DBusMessageIter iter, dict_iter;
1662         struct wpas_dbus_priv *iface;
1663
1664         wpa_printf(MSG_DEBUG, "%s", __func__);
1665
1666         iface = wpa_s->global->dbus;
1667         /* Do nothing if the control interface is not turned on */
1668         if (iface == NULL)
1669                 return;
1670
1671         if (wpa_s->p2p_mgmt)
1672                 wpa_s = wpa_s->parent;
1673         if (!wpa_s->dbus_new_path)
1674                 return;
1675
1676         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1677                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1678                                       "InvitationResult");
1679
1680         if (msg == NULL)
1681                 return;
1682
1683         dbus_message_iter_init_append(msg, &iter);
1684         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1685             !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1686             (bssid &&
1687              !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1688                                               (const char *) bssid,
1689                                               ETH_ALEN)) ||
1690             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1691                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1692         else
1693                 dbus_connection_send(iface->con, msg, NULL);
1694         dbus_message_unref(msg);
1695 }
1696
1697
1698 /**
1699  *
1700  * Method to emit a signal for a peer joining the group.
1701  * The signal will carry path to the group member object
1702  * constructed using p2p i/f addr used for connecting.
1703  *
1704  * @wpa_s: %wpa_supplicant network interface data
1705  * @peer_addr: P2P Device Address of the peer joining the group
1706  */
1707 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1708                                       const u8 *peer_addr)
1709 {
1710         struct wpas_dbus_priv *iface;
1711         DBusMessage *msg;
1712         DBusMessageIter iter;
1713         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1714         struct wpa_supplicant *parent;
1715
1716         iface = wpa_s->global->dbus;
1717
1718         /* Do nothing if the control interface is not turned on */
1719         if (iface == NULL)
1720                 return;
1721
1722         if (!wpa_s->dbus_groupobj_path)
1723                 return;
1724
1725         parent = wpa_s->parent;
1726         if (parent->p2p_mgmt)
1727                 parent = parent->parent;
1728         if (!parent->dbus_new_path)
1729                 return;
1730
1731         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1732                         "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1733                         COMPACT_MACSTR,
1734                         parent->dbus_new_path, MAC2STR(peer_addr));
1735
1736         msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1737                                       WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1738                                       "PeerJoined");
1739         if (msg == NULL)
1740                 return;
1741
1742         dbus_message_iter_init_append(msg, &iter);
1743         path = peer_obj_path;
1744         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1745                                             &path)) {
1746                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1747         } else {
1748                 dbus_connection_send(iface->con, msg, NULL);
1749                 wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1750         }
1751         dbus_message_unref(msg);
1752 }
1753
1754
1755 /**
1756  *
1757  * Method to emit a signal for a peer disconnecting the group.
1758  * The signal will carry path to the group member object
1759  * constructed using the P2P Device Address of the peer.
1760  *
1761  * @wpa_s: %wpa_supplicant network interface data
1762  * @peer_addr: P2P Device Address of the peer joining the group
1763  */
1764 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1765                                             const u8 *peer_addr)
1766 {
1767         struct wpas_dbus_priv *iface;
1768         DBusMessage *msg;
1769         DBusMessageIter iter;
1770         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1771         struct wpa_supplicant *parent;
1772
1773         iface = wpa_s->global->dbus;
1774
1775         /* Do nothing if the control interface is not turned on */
1776         if (iface == NULL)
1777                 return;
1778
1779         if (!wpa_s->dbus_groupobj_path)
1780                 return;
1781
1782         parent = wpa_s->parent;
1783         if (parent->p2p_mgmt)
1784                 parent = parent->parent;
1785         if (!parent->dbus_new_path)
1786                 return;
1787
1788         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1789                         "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1790                         COMPACT_MACSTR,
1791                         parent->dbus_new_path, MAC2STR(peer_addr));
1792
1793         msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1794                                       WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1795                                       "PeerDisconnected");
1796         if (msg == NULL)
1797                 return;
1798
1799         dbus_message_iter_init_append(msg, &iter);
1800         path = peer_obj_path;
1801         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1802                                             &path)) {
1803                 wpa_printf(MSG_ERROR,
1804                            "dbus: Failed to construct PeerDisconnected signal");
1805         } else {
1806                 dbus_connection_send(iface->con, msg, NULL);
1807                 wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1808         }
1809         dbus_message_unref(msg);
1810 }
1811
1812
1813 /**
1814  *
1815  * Method to emit a signal for a service discovery request.
1816  * The signal will carry station address, frequency, dialog token,
1817  * update indicator and it tlvs
1818  *
1819  * @wpa_s: %wpa_supplicant network interface data
1820  * @sa: station addr (p2p i/f) of the peer
1821  * @dialog_token: service discovery request dialog token
1822  * @update_indic: service discovery request update indicator
1823  * @tlvs: service discovery request genrated byte array of tlvs
1824  * @tlvs_len: service discovery request tlvs length
1825  */
1826 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1827                                      int freq, const u8 *sa, u8 dialog_token,
1828                                      u16 update_indic, const u8 *tlvs,
1829                                      size_t tlvs_len)
1830 {
1831         DBusMessage *msg;
1832         DBusMessageIter iter, dict_iter;
1833         struct wpas_dbus_priv *iface;
1834         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1835
1836         iface = wpa_s->global->dbus;
1837
1838         /* Do nothing if the control interface is not turned on */
1839         if (iface == NULL)
1840                 return;
1841
1842         if (wpa_s->p2p_mgmt)
1843                 wpa_s = wpa_s->parent;
1844         if (!wpa_s->dbus_new_path)
1845                 return;
1846
1847         /* Check if this is a known peer */
1848         if (!p2p_peer_known(wpa_s->global->p2p, sa))
1849                 return;
1850
1851         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1852                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1853                                       "ServiceDiscoveryRequest");
1854         if (msg == NULL)
1855                 return;
1856
1857         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1858                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1859                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1860
1861         path = peer_obj_path;
1862
1863         dbus_message_iter_init_append(msg, &iter);
1864         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1865             !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1866                                               path) ||
1867             !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1868             !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1869                                         dialog_token) ||
1870             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1871                                          update_indic) ||
1872             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1873                                              (const char *) tlvs,
1874                                              tlvs_len) ||
1875             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1876                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1877         else
1878                 dbus_connection_send(iface->con, msg, NULL);
1879         dbus_message_unref(msg);
1880 }
1881
1882
1883 /**
1884  *
1885  * Method to emit a signal for a service discovery response.
1886  * The signal will carry station address, update indicator and it
1887  * tlvs
1888  *
1889  * @wpa_s: %wpa_supplicant network interface data
1890  * @sa: station addr (p2p i/f) of the peer
1891  * @update_indic: service discovery request update indicator
1892  * @tlvs: service discovery request genrated byte array of tlvs
1893  * @tlvs_len: service discovery request tlvs length
1894  */
1895 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1896                                       const u8 *sa, u16 update_indic,
1897                                       const u8 *tlvs, size_t tlvs_len)
1898 {
1899         DBusMessage *msg;
1900         DBusMessageIter iter, dict_iter;
1901         struct wpas_dbus_priv *iface;
1902         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1903
1904         iface = wpa_s->global->dbus;
1905
1906         /* Do nothing if the control interface is not turned on */
1907         if (iface == NULL)
1908                 return;
1909
1910         if (wpa_s->p2p_mgmt)
1911                 wpa_s = wpa_s->parent;
1912         if (!wpa_s->dbus_new_path)
1913                 return;
1914
1915         /* Check if this is a known peer */
1916         if (!p2p_peer_known(wpa_s->global->p2p, sa))
1917                 return;
1918
1919         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1920                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1921                                       "ServiceDiscoveryResponse");
1922         if (msg == NULL)
1923                 return;
1924
1925         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1926                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1927                     COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1928
1929         path = peer_obj_path;
1930
1931         dbus_message_iter_init_append(msg, &iter);
1932         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1933             !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1934                                               path) ||
1935             !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1936                                          update_indic) ||
1937             !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1938                                              (const char *) tlvs,
1939                                              tlvs_len) ||
1940             !wpa_dbus_dict_close_write(&iter, &dict_iter))
1941                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1942         else
1943                 dbus_connection_send(iface->con, msg, NULL);
1944         dbus_message_unref(msg);
1945 }
1946
1947
1948 /**
1949  * wpas_dbus_signal_persistent_group - Send a persistent group related
1950  *      event signal
1951  * @wpa_s: %wpa_supplicant network interface data
1952  * @id: new persistent group id
1953  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1954  * @properties: determines if add second argument with object properties
1955  *
1956  * Notify listeners about an event related to persistent groups.
1957  */
1958 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1959                                               int id, const char *sig_name,
1960                                               dbus_bool_t properties)
1961 {
1962         struct wpas_dbus_priv *iface;
1963         DBusMessage *msg;
1964         DBusMessageIter iter;
1965         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1966
1967         iface = wpa_s->global->dbus;
1968
1969         /* Do nothing if the control interface is not turned on */
1970         if (iface == NULL)
1971                 return;
1972
1973         if (wpa_s->p2p_mgmt)
1974                 wpa_s = wpa_s->parent;
1975         if (!wpa_s->dbus_new_path)
1976                 return;
1977
1978         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1979                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1980                     wpa_s->dbus_new_path, id);
1981
1982         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1983                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1984                                       sig_name);
1985         if (msg == NULL)
1986                 return;
1987
1988         dbus_message_iter_init_append(msg, &iter);
1989         path = pgrp_obj_path;
1990         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1991                                             &path) ||
1992             (properties &&
1993              !wpa_dbus_get_object_properties(
1994                      iface, pgrp_obj_path,
1995                      WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
1996                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1997         else
1998                 dbus_connection_send(iface->con, msg, NULL);
1999
2000         dbus_message_unref(msg);
2001 }
2002
2003
2004 /**
2005  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
2006  *      added signal
2007  * @wpa_s: %wpa_supplicant network interface data
2008  * @id: new persistent group id
2009  *
2010  * Notify listeners about addition of a new persistent group.
2011  */
2012 static void wpas_dbus_signal_persistent_group_added(
2013         struct wpa_supplicant *wpa_s, int id)
2014 {
2015         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
2016                                           TRUE);
2017 }
2018
2019
2020 /**
2021  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
2022  *      removed signal
2023  * @wpa_s: %wpa_supplicant network interface data
2024  * @id: persistent group id
2025  *
2026  * Notify listeners about removal of a persistent group.
2027  */
2028 static void wpas_dbus_signal_persistent_group_removed(
2029         struct wpa_supplicant *wpa_s, int id)
2030 {
2031         wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
2032                                           FALSE);
2033 }
2034
2035
2036 /**
2037  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
2038  * @wpa_s: %wpa_supplicant network interface data
2039  * @fail: WPS failure information
2040  *
2041  * Sends Event dbus signal with name "fail" and dictionary containing
2042  * "msg" field with fail message number (int32) as arguments
2043  */
2044 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
2045                                      struct wps_event_fail *fail)
2046 {
2047
2048         DBusMessage *msg;
2049         DBusMessageIter iter, dict_iter;
2050         struct wpas_dbus_priv *iface;
2051         char *key = "fail";
2052
2053         iface = wpa_s->global->dbus;
2054
2055         /* Do nothing if the control interface is not turned on */
2056         if (iface == NULL)
2057                 return;
2058
2059         if (wpa_s->p2p_mgmt)
2060                 wpa_s = wpa_s->parent;
2061
2062         if (!wpa_s->dbus_new_path)
2063                 return;
2064         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2065                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2066                                       "WpsFailed");
2067         if (msg == NULL)
2068                 return;
2069
2070         dbus_message_iter_init_append(msg, &iter);
2071
2072         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
2073             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2074             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
2075             !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
2076                                         fail->config_error) ||
2077             !wpa_dbus_dict_close_write(&iter, &dict_iter))
2078                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2079         else
2080                 dbus_connection_send(iface->con, msg, NULL);
2081
2082         dbus_message_unref(msg);
2083 }
2084
2085
2086 /**
2087  * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
2088  * @wpa_s: %wpa_supplicant network interface data
2089  * @reason: indicates the reason code for group formation failure
2090  *
2091  * Sends Event dbus signal and string reason code when available.
2092  */
2093 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
2094                                                   const char *reason)
2095 {
2096         DBusMessage *msg;
2097         struct wpas_dbus_priv *iface;
2098
2099         iface = wpa_s->global->dbus;
2100
2101         /* Do nothing if the control interface is not turned on */
2102         if (iface == NULL)
2103                 return;
2104
2105         if (wpa_s->p2p_mgmt)
2106                 wpa_s = wpa_s->parent;
2107
2108         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2109                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2110                                       "GroupFormationFailure");
2111         if (msg == NULL)
2112                 return;
2113
2114         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
2115                                      DBUS_TYPE_INVALID))
2116                 dbus_connection_send(iface->con, msg, NULL);
2117         else
2118                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2119
2120         dbus_message_unref(msg);
2121 }
2122
2123
2124 /**
2125  * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
2126  * @wpa_s: %wpa_supplicant network interface data
2127  * @sa: Source address of the Invitation Request
2128  * @dev_add: GO Device Address
2129  * @bssid: P2P Group BSSID or %NULL if not received
2130  * @id: Persistent group id or %0 if not persistent group
2131  * @op_freq: Operating frequency for the group
2132  */
2133
2134 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
2135                                               const u8 *sa, const u8 *dev_addr,
2136                                               const u8 *bssid, int id,
2137                                               int op_freq)
2138 {
2139         DBusMessage *msg;
2140         DBusMessageIter iter, dict_iter;
2141         struct wpas_dbus_priv *iface;
2142
2143         iface = wpa_s->global->dbus;
2144
2145         /* Do nothing if the control interface is not turned on */
2146         if (iface == NULL)
2147                 return;
2148
2149         if (wpa_s->p2p_mgmt)
2150                 wpa_s = wpa_s->parent;
2151
2152         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2153                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2154                                       "InvitationReceived");
2155         if (msg == NULL)
2156                 return;
2157
2158         dbus_message_iter_init_append(msg, &iter);
2159         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2160             (sa &&
2161              !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
2162                                               (const char *) sa, ETH_ALEN)) ||
2163             (dev_addr &&
2164              !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
2165                                               (const char *) dev_addr,
2166                                               ETH_ALEN)) ||
2167             (bssid &&
2168              !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
2169                                               (const char *) bssid,
2170                                               ETH_ALEN)) ||
2171             (id &&
2172              !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
2173             !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
2174             !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
2175                 dbus_message_unref(msg);
2176                 return;
2177         }
2178
2179         dbus_connection_send(iface->con, msg, NULL);
2180         dbus_message_unref(msg);
2181 }
2182
2183
2184 #endif /* CONFIG_P2P */
2185
2186
2187 /**
2188  * wpas_dbus_signal_prop_changed - Signals change of property
2189  * @wpa_s: %wpa_supplicant network interface data
2190  * @property: indicates which property has changed
2191  *
2192  * Sends PropertyChanged signals with path, interface and arguments
2193  * depending on which property has changed.
2194  */
2195 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2196                                    enum wpas_dbus_prop property)
2197 {
2198         char *prop;
2199         dbus_bool_t flush;
2200
2201         if (wpa_s->dbus_new_path == NULL)
2202                 return; /* Skip signal since D-Bus setup is not yet ready */
2203
2204         flush = FALSE;
2205         switch (property) {
2206         case WPAS_DBUS_PROP_AP_SCAN:
2207                 prop = "ApScan";
2208                 break;
2209         case WPAS_DBUS_PROP_SCANNING:
2210                 prop = "Scanning";
2211                 break;
2212         case WPAS_DBUS_PROP_STATE:
2213                 prop = "State";
2214                 break;
2215         case WPAS_DBUS_PROP_CURRENT_BSS:
2216                 prop = "CurrentBSS";
2217                 break;
2218         case WPAS_DBUS_PROP_CURRENT_NETWORK:
2219                 prop = "CurrentNetwork";
2220                 break;
2221         case WPAS_DBUS_PROP_BSSS:
2222                 prop = "BSSs";
2223                 break;
2224         case WPAS_DBUS_PROP_STATIONS:
2225                 prop = "Stations";
2226                 break;
2227         case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2228                 prop = "CurrentAuthMode";
2229                 break;
2230         case WPAS_DBUS_PROP_DISCONNECT_REASON:
2231                 prop = "DisconnectReason";
2232                 flush = TRUE;
2233                 break;
2234         case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2235                 prop = "AuthStatusCode";
2236                 flush = TRUE;
2237                 break;
2238         case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2239                 prop = "AssocStatusCode";
2240                 flush = TRUE;
2241                 break;
2242         case WPAS_DBUS_PROP_ROAM_TIME:
2243                 prop = "RoamTime";
2244                 break;
2245         case WPAS_DBUS_PROP_ROAM_COMPLETE:
2246                 prop = "RoamComplete";
2247                 break;
2248         case WPAS_DBUS_PROP_SESSION_LENGTH:
2249                 prop = "SessionLength";
2250                 break;
2251         case WPAS_DBUS_PROP_BSS_TM_STATUS:
2252                 prop = "BSSTMStatus";
2253                 break;
2254         default:
2255                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2256                            __func__, property);
2257                 return;
2258         }
2259
2260         wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2261                                        wpa_s->dbus_new_path,
2262                                        WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2263         if (flush) {
2264                 wpa_dbus_flush_object_changed_properties(
2265                         wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2266         }
2267 }
2268
2269
2270 /**
2271  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2272  * @wpa_s: %wpa_supplicant network interface data
2273  * @property: indicates which property has changed
2274  * @id: unique BSS identifier
2275  *
2276  * Sends PropertyChanged signals with path, interface, and arguments depending
2277  * on which property has changed.
2278  */
2279 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2280                                        enum wpas_dbus_bss_prop property,
2281                                        unsigned int id)
2282 {
2283         char path[WPAS_DBUS_OBJECT_PATH_MAX];
2284         char *prop;
2285
2286         if (!wpa_s->dbus_new_path)
2287                 return;
2288
2289         switch (property) {
2290         case WPAS_DBUS_BSS_PROP_SIGNAL:
2291                 prop = "Signal";
2292                 break;
2293         case WPAS_DBUS_BSS_PROP_FREQ:
2294                 prop = "Frequency";
2295                 break;
2296         case WPAS_DBUS_BSS_PROP_MODE:
2297                 prop = "Mode";
2298                 break;
2299         case WPAS_DBUS_BSS_PROP_PRIVACY:
2300                 prop = "Privacy";
2301                 break;
2302         case WPAS_DBUS_BSS_PROP_RATES:
2303                 prop = "Rates";
2304                 break;
2305         case WPAS_DBUS_BSS_PROP_WPA:
2306                 prop = "WPA";
2307                 break;
2308         case WPAS_DBUS_BSS_PROP_RSN:
2309                 prop = "RSN";
2310                 break;
2311         case WPAS_DBUS_BSS_PROP_WPS:
2312                 prop = "WPS";
2313                 break;
2314         case WPAS_DBUS_BSS_PROP_IES:
2315                 prop = "IEs";
2316                 break;
2317         case WPAS_DBUS_BSS_PROP_AGE:
2318                 prop = "Age";
2319                 break;
2320         default:
2321                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2322                            __func__, property);
2323                 return;
2324         }
2325
2326         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2327                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2328                     wpa_s->dbus_new_path, id);
2329
2330         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2331                                        WPAS_DBUS_NEW_IFACE_BSS, prop);
2332 }
2333
2334
2335 /**
2336  * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
2337  * @wpa_s: %wpa_supplicant network interface data
2338  * @property: indicates which property has changed
2339  * @address: unique BSS identifier
2340  *
2341  * Sends PropertyChanged signals with path, interface, and arguments depending
2342  * on which property has changed.
2343  */
2344 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
2345                                        enum wpas_dbus_bss_prop property,
2346                                        u8 address[ETH_ALEN])
2347 {
2348         char path[WPAS_DBUS_OBJECT_PATH_MAX];
2349         char *prop;
2350
2351         switch (property) {
2352         case WPAS_DBUS_STA_PROP_ADDRESS:
2353                 prop = "Address";
2354                 break;
2355         default:
2356                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2357                            __func__, property);
2358                 return;
2359         }
2360
2361         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2362                     "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
2363                     wpa_s->dbus_new_path, MAC2STR(address));
2364
2365         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2366                                        WPAS_DBUS_NEW_IFACE_STA, prop);
2367 }
2368
2369
2370 /**
2371  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2372  * @global: wpa_global structure
2373  *
2374  * Sends PropertyChanged signals informing that debug level has changed.
2375  */
2376 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2377 {
2378         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2379                                        WPAS_DBUS_NEW_INTERFACE,
2380                                        "DebugLevel");
2381 }
2382
2383
2384 /**
2385  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2386  * @global: wpa_global structure
2387  *
2388  * Sends PropertyChanged signals informing that debug timestamp has changed.
2389  */
2390 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2391 {
2392         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2393                                        WPAS_DBUS_NEW_INTERFACE,
2394                                        "DebugTimestamp");
2395 }
2396
2397
2398 /**
2399  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2400  * @global: wpa_global structure
2401  *
2402  * Sends PropertyChanged signals informing that debug show_keys has changed.
2403  */
2404 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2405 {
2406         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2407                                        WPAS_DBUS_NEW_INTERFACE,
2408                                        "DebugShowKeys");
2409 }
2410
2411
2412 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2413                                void *priv,
2414                                WPADBusArgumentFreeFunction priv_free,
2415                                const struct wpa_dbus_method_desc *methods,
2416                                const struct wpa_dbus_property_desc *properties,
2417                                const struct wpa_dbus_signal_desc *signals)
2418 {
2419         int n;
2420
2421         obj_desc->user_data = priv;
2422         obj_desc->user_data_free_func = priv_free;
2423         obj_desc->methods = methods;
2424         obj_desc->properties = properties;
2425         obj_desc->signals = signals;
2426
2427         for (n = 0; properties && properties->dbus_property; properties++)
2428                 n++;
2429
2430         obj_desc->prop_changed_flags = os_zalloc(n);
2431         if (!obj_desc->prop_changed_flags)
2432                 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2433                            __func__);
2434 }
2435
2436
2437 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2438         { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2439           (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2440           {
2441                   { "args", "a{sv}", ARG_IN },
2442                   { "path", "o", ARG_OUT },
2443                   END_ARGS
2444           }
2445         },
2446         { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2447           (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2448           {
2449                   { "path", "o", ARG_IN },
2450                   END_ARGS
2451           }
2452         },
2453         { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2454           (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2455           {
2456                   { "ifname", "s", ARG_IN },
2457                   { "path", "o", ARG_OUT },
2458                   END_ARGS
2459           }
2460         },
2461         { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2462           (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2463           {
2464                 END_ARGS
2465           }
2466         },
2467         { NULL, NULL, NULL, { END_ARGS } }
2468 };
2469
2470 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2471         { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2472           wpas_dbus_getter_debug_level,
2473           wpas_dbus_setter_debug_level,
2474           NULL
2475         },
2476         { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2477           wpas_dbus_getter_debug_timestamp,
2478           wpas_dbus_setter_debug_timestamp,
2479           NULL
2480         },
2481         { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2482           wpas_dbus_getter_debug_show_keys,
2483           wpas_dbus_setter_debug_show_keys,
2484           NULL
2485         },
2486         { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2487           wpas_dbus_getter_interfaces,
2488           NULL,
2489           NULL
2490         },
2491         { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2492           wpas_dbus_getter_eap_methods,
2493           NULL,
2494           NULL
2495         },
2496         { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2497           wpas_dbus_getter_global_capabilities,
2498           NULL,
2499           NULL
2500         },
2501 #ifdef CONFIG_WIFI_DISPLAY
2502         { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2503           wpas_dbus_getter_global_wfd_ies,
2504           wpas_dbus_setter_global_wfd_ies,
2505           NULL
2506         },
2507 #endif /* CONFIG_WIFI_DISPLAY */
2508         { NULL, NULL, NULL, NULL, NULL, NULL }
2509 };
2510
2511 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2512         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2513           {
2514                   { "path", "o", ARG_OUT },
2515                   { "properties", "a{sv}", ARG_OUT },
2516                   END_ARGS
2517           }
2518         },
2519         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2520           {
2521                   { "path", "o", ARG_OUT },
2522                   END_ARGS
2523           }
2524         },
2525         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2526         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2527           {
2528                   { "properties", "a{sv}", ARG_OUT },
2529                   END_ARGS
2530           }
2531         },
2532         { NULL, NULL, { END_ARGS } }
2533 };
2534
2535
2536 static char * uscore_to_dbus(const char *uscore)
2537 {
2538         const char *p = uscore;
2539         char *str, *s;
2540         dbus_bool_t last_was_uscore = TRUE;
2541
2542         s = str = os_zalloc(os_strlen(uscore) + 1);
2543         if (!str)
2544                 return NULL;
2545         while (p && *p) {
2546                 if (*p == '_') {
2547                         last_was_uscore = TRUE;
2548                 } else {
2549                         *s++ = last_was_uscore ? toupper(*p) : *p;
2550                         last_was_uscore = FALSE;
2551                 }
2552                 p++;
2553         }
2554
2555         return str;
2556 }
2557
2558
2559 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2560
2561
2562 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2563 {
2564         int idx = priv->globals_start;
2565
2566         /* Free all allocated property values */
2567         while (priv->all_interface_properties[idx].dbus_property)
2568                 os_free((char *)
2569                         priv->all_interface_properties[idx++].dbus_property);
2570         os_free((char *) priv->all_interface_properties);
2571 }
2572
2573
2574 /**
2575  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2576  * @global: Pointer to global data from wpa_supplicant_init()
2577  * Returns: 0 on success or -1 on failure
2578  *
2579  * Initialize the dbus control interface for wpa_supplicant and start
2580  * receiving commands from external programs over the bus.
2581  */
2582 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2583 {
2584         struct wpa_dbus_object_desc *obj_desc;
2585         int ret;
2586
2587         ret = wpa_dbus_ctrl_iface_props_init(priv);
2588         if (ret < 0) {
2589                 wpa_printf(MSG_ERROR,
2590                            "dbus: Not enough memory to init interface properties");
2591                 return -1;
2592         }
2593
2594         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2595         if (!obj_desc) {
2596                 wpa_printf(MSG_ERROR,
2597                            "Not enough memory to create object description");
2598                 goto error;
2599         }
2600
2601         wpas_dbus_register(obj_desc, priv->global, NULL,
2602                            wpas_dbus_global_methods,
2603                            wpas_dbus_global_properties,
2604                            wpas_dbus_global_signals);
2605
2606         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2607                    WPAS_DBUS_NEW_PATH);
2608         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2609                                        WPAS_DBUS_NEW_SERVICE,
2610                                        obj_desc);
2611         if (ret < 0) {
2612                 free_dbus_object_desc(obj_desc);
2613                 goto error;
2614         }
2615
2616         priv->dbus_new_initialized = 1;
2617         return 0;
2618
2619 error:
2620         wpa_dbus_ctrl_iface_props_deinit(priv);
2621         return -1;
2622 }
2623
2624
2625 /**
2626  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2627  * wpa_supplicant
2628  * @priv: Pointer to dbus private data from wpas_dbus_init()
2629  *
2630  * Deinitialize the dbus control interface that was initialized with
2631  * wpas_dbus_ctrl_iface_init().
2632  */
2633 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2634 {
2635         if (!priv->dbus_new_initialized)
2636                 return;
2637         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2638                    WPAS_DBUS_NEW_PATH);
2639         dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2640         wpa_dbus_ctrl_iface_props_deinit(priv);
2641 }
2642
2643
2644 static void wpa_dbus_free(void *ptr)
2645 {
2646         os_free(ptr);
2647 }
2648
2649
2650 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2651         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2652           wpas_dbus_getter_network_properties,
2653           wpas_dbus_setter_network_properties,
2654           NULL
2655         },
2656         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2657           wpas_dbus_getter_enabled,
2658           wpas_dbus_setter_enabled,
2659           NULL
2660         },
2661         { NULL, NULL, NULL, NULL, NULL, NULL }
2662 };
2663
2664
2665 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2666         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2667         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2668           {
2669                   { "properties", "a{sv}", ARG_OUT },
2670                   END_ARGS
2671           }
2672         },
2673         { NULL, NULL, { END_ARGS } }
2674 };
2675
2676
2677 /**
2678  * wpas_dbus_register_network - Register a configured network with dbus
2679  * @wpa_s: wpa_supplicant interface structure
2680  * @ssid: network configuration data
2681  * Returns: 0 on success, -1 on failure
2682  *
2683  * Registers network representing object with dbus
2684  */
2685 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2686                                struct wpa_ssid *ssid)
2687 {
2688         struct wpas_dbus_priv *ctrl_iface;
2689         struct wpa_dbus_object_desc *obj_desc;
2690         struct network_handler_args *arg;
2691         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2692
2693 #ifdef CONFIG_P2P
2694         /*
2695          * If it is a persistent group register it as such.
2696          * This is to handle cases where an interface is being initialized
2697          * with a list of networks read from config.
2698          */
2699         if (network_is_persistent_group(ssid))
2700                 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2701 #endif /* CONFIG_P2P */
2702
2703         /* Do nothing if the control interface is not turned on */
2704         if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2705                 return 0;
2706         ctrl_iface = wpa_s->global->dbus;
2707         if (ctrl_iface == NULL)
2708                 return 0;
2709
2710         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2711                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2712                     wpa_s->dbus_new_path, ssid->id);
2713
2714         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2715                    net_obj_path);
2716         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2717         if (!obj_desc) {
2718                 wpa_printf(MSG_ERROR,
2719                            "Not enough memory to create object description");
2720                 goto err;
2721         }
2722
2723         /* allocate memory for handlers arguments */
2724         arg = os_zalloc(sizeof(struct network_handler_args));
2725         if (!arg) {
2726                 wpa_printf(MSG_ERROR,
2727                            "Not enough memory to create arguments for method");
2728                 goto err;
2729         }
2730
2731         arg->wpa_s = wpa_s;
2732         arg->ssid = ssid;
2733
2734         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2735                            wpas_dbus_network_properties,
2736                            wpas_dbus_network_signals);
2737
2738         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2739                                                wpa_s->ifname, obj_desc))
2740                 goto err;
2741
2742         wpas_dbus_signal_network_added(wpa_s, ssid->id);
2743
2744         return 0;
2745
2746 err:
2747         free_dbus_object_desc(obj_desc);
2748         return -1;
2749 }
2750
2751
2752 /**
2753  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2754  * @wpa_s: wpa_supplicant interface structure
2755  * @nid: network id
2756  * Returns: 0 on success, -1 on failure
2757  *
2758  * Unregisters network representing object from dbus
2759  */
2760 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2761 {
2762         struct wpas_dbus_priv *ctrl_iface;
2763         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2764         int ret;
2765 #ifdef CONFIG_P2P
2766         struct wpa_ssid *ssid;
2767
2768         ssid = wpa_config_get_network(wpa_s->conf, nid);
2769
2770         /* If it is a persistent group unregister it as such */
2771         if (ssid && network_is_persistent_group(ssid))
2772                 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2773 #endif /* CONFIG_P2P */
2774
2775         /* Do nothing if the control interface is not turned on */
2776         if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2777                 return 0;
2778         ctrl_iface = wpa_s->global->dbus;
2779         if (ctrl_iface == NULL)
2780                 return 0;
2781
2782         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2783                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2784                     wpa_s->dbus_new_path, nid);
2785
2786         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2787                    net_obj_path);
2788         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2789
2790         if (!ret)
2791                 wpas_dbus_signal_network_removed(wpa_s, nid);
2792
2793         return ret;
2794 }
2795
2796
2797 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2798         { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2799           wpas_dbus_getter_bss_ssid,
2800           NULL,
2801           NULL
2802         },
2803         { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2804           wpas_dbus_getter_bss_bssid,
2805           NULL,
2806           NULL
2807         },
2808         { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2809           wpas_dbus_getter_bss_privacy,
2810           NULL,
2811           NULL
2812         },
2813         { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2814           wpas_dbus_getter_bss_mode,
2815           NULL,
2816           NULL
2817         },
2818         { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2819           wpas_dbus_getter_bss_signal,
2820           NULL,
2821           NULL
2822         },
2823         { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2824           wpas_dbus_getter_bss_frequency,
2825           NULL,
2826           NULL
2827         },
2828         { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2829           wpas_dbus_getter_bss_rates,
2830           NULL,
2831           NULL
2832         },
2833         { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2834           wpas_dbus_getter_bss_wpa,
2835           NULL,
2836           NULL
2837         },
2838         { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2839           wpas_dbus_getter_bss_rsn,
2840           NULL,
2841           NULL
2842         },
2843         { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2844           wpas_dbus_getter_bss_wps,
2845           NULL,
2846           NULL
2847         },
2848         { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2849           wpas_dbus_getter_bss_ies,
2850           NULL,
2851           NULL
2852         },
2853         { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2854           wpas_dbus_getter_bss_age,
2855           NULL,
2856           NULL
2857         },
2858         {
2859           "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2860           wpas_dbus_getter_roam_time,
2861           NULL,
2862           NULL
2863         },
2864         {
2865           "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2866           wpas_dbus_getter_roam_complete,
2867           NULL,
2868           NULL
2869         },
2870         {
2871           "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2872           wpas_dbus_getter_session_length,
2873           NULL,
2874           NULL
2875         },
2876         {
2877           "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2878           wpas_dbus_getter_bss_tm_status,
2879           NULL,
2880           NULL
2881         },
2882         { NULL, NULL, NULL, NULL, NULL, NULL }
2883 };
2884
2885
2886 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2887         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2888         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2889           {
2890                   { "properties", "a{sv}", ARG_OUT },
2891                   END_ARGS
2892           }
2893         },
2894         { NULL, NULL, { END_ARGS } }
2895 };
2896
2897
2898 /**
2899  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2900  * @wpa_s: wpa_supplicant interface structure
2901  * @bssid: scanned network bssid
2902  * @id: unique BSS identifier
2903  * Returns: 0 on success, -1 on failure
2904  *
2905  * Unregisters BSS representing object from dbus
2906  */
2907 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2908                              u8 bssid[ETH_ALEN], unsigned int id)
2909 {
2910         struct wpas_dbus_priv *ctrl_iface;
2911         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2912
2913         /* Do nothing if the control interface is not turned on */
2914         if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2915                 return 0;
2916         ctrl_iface = wpa_s->global->dbus;
2917         if (ctrl_iface == NULL)
2918                 return 0;
2919
2920         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2921                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2922                     wpa_s->dbus_new_path, id);
2923
2924         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2925                    bss_obj_path);
2926         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2927                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2928                            bss_obj_path);
2929                 return -1;
2930         }
2931
2932         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2933         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2934
2935         return 0;
2936 }
2937
2938
2939 /**
2940  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2941  * @wpa_s: wpa_supplicant interface structure
2942  * @bssid: scanned network bssid
2943  * @id: unique BSS identifier
2944  * Returns: 0 on success, -1 on failure
2945  *
2946  * Registers BSS representing object with dbus
2947  */
2948 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2949                            u8 bssid[ETH_ALEN], unsigned int id)
2950 {
2951         struct wpas_dbus_priv *ctrl_iface;
2952         struct wpa_dbus_object_desc *obj_desc;
2953         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2954         struct bss_handler_args *arg;
2955
2956         /* Do nothing if the control interface is not turned on */
2957         if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2958                 return 0;
2959         ctrl_iface = wpa_s->global->dbus;
2960         if (ctrl_iface == NULL)
2961                 return 0;
2962
2963         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2964                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2965                     wpa_s->dbus_new_path, id);
2966
2967         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2968         if (!obj_desc) {
2969                 wpa_printf(MSG_ERROR,
2970                            "Not enough memory to create object description");
2971                 goto err;
2972         }
2973
2974         arg = os_zalloc(sizeof(struct bss_handler_args));
2975         if (!arg) {
2976                 wpa_printf(MSG_ERROR,
2977                            "Not enough memory to create arguments for handler");
2978                 goto err;
2979         }
2980         arg->wpa_s = wpa_s;
2981         arg->id = id;
2982
2983         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2984                            wpas_dbus_bss_properties,
2985                            wpas_dbus_bss_signals);
2986
2987         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2988                    bss_obj_path);
2989         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2990                                                wpa_s->ifname, obj_desc)) {
2991                 wpa_printf(MSG_ERROR,
2992                            "Cannot register BSSID dbus object %s.",
2993                            bss_obj_path);
2994                 goto err;
2995         }
2996
2997         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2998         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2999
3000         return 0;
3001
3002 err:
3003         free_dbus_object_desc(obj_desc);
3004         return -1;
3005 }
3006
3007
3008 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3009         { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3010           wpas_dbus_getter_sta_address,
3011           NULL, NULL
3012         },
3013         { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3014           wpas_dbus_getter_sta_aid,
3015           NULL, NULL
3016         },
3017         { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3018           wpas_dbus_getter_sta_caps,
3019           NULL, NULL
3020         },
3021         { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3022           wpas_dbus_getter_sta_rx_packets,
3023           NULL, NULL
3024         },
3025         { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3026           wpas_dbus_getter_sta_tx_packets,
3027           NULL, NULL
3028         },
3029         { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3030           wpas_dbus_getter_sta_rx_bytes,
3031           NULL, NULL
3032         },
3033         { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3034           wpas_dbus_getter_sta_tx_bytes,
3035           NULL, NULL
3036         },
3037         { NULL, NULL, NULL, NULL, NULL, NULL }
3038 };
3039
3040
3041 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3042         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3043         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3044           {
3045                   { "properties", "a{sv}", ARG_OUT },
3046                   END_ARGS
3047           }
3048         },
3049         { NULL, NULL, { END_ARGS } }
3050 };
3051
3052
3053 /**
3054  * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3055  * @wpa_s: wpa_supplicant interface structure
3056  * @sta: station MAC address
3057  * Returns: 0 on success, -1 on failure
3058  *
3059  * Unregisters STA representing object from dbus.
3060  */
3061 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3062 {
3063         struct wpas_dbus_priv *ctrl_iface;
3064         char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3065
3066         /* Do nothing if the control interface is not turned on */
3067         if (!wpa_s || !wpa_s->global)
3068                 return 0;
3069         ctrl_iface = wpa_s->global->dbus;
3070         if (!ctrl_iface)
3071                 return 0;
3072
3073         os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3074                     "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3075                     wpa_s->dbus_new_path, MAC2STR(sta));
3076
3077         wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3078                    station_obj_path);
3079         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3080                                                  station_obj_path)) {
3081                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3082                            station_obj_path);
3083                 return -1;
3084         }
3085
3086         wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3087         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3088
3089         return 0;
3090 }
3091
3092
3093 /**
3094  * wpas_dbus_register_sta - Register a connected station with dbus
3095  * @wpa_s: wpa_supplicant interface structure
3096  * @sta: station MAC address
3097  * Returns: 0 on success, -1 on failure
3098  *
3099  * Registers STA representing object with dbus.
3100  */
3101 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3102 {
3103         struct wpas_dbus_priv *ctrl_iface;
3104         struct wpa_dbus_object_desc *obj_desc;
3105         char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3106         struct sta_handler_args *arg;
3107
3108         /* Do nothing if the control interface is not turned on */
3109         if (!wpa_s || !wpa_s->global)
3110                 return 0;
3111         ctrl_iface = wpa_s->global->dbus;
3112         if (!ctrl_iface)
3113                 return 0;
3114
3115         os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3116                     "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3117                     wpa_s->dbus_new_path, MAC2STR(sta));
3118
3119         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3120         if (!obj_desc) {
3121                 wpa_printf(MSG_ERROR,
3122                            "Not enough memory to create object description");
3123                 goto err;
3124         }
3125
3126         arg = os_zalloc(sizeof(struct sta_handler_args));
3127         if (!arg) {
3128                 wpa_printf(MSG_ERROR,
3129                            "Not enough memory to create arguments for handler");
3130                 goto err;
3131         }
3132         arg->wpa_s = wpa_s;
3133         arg->sta = sta;
3134
3135         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3136                            wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3137
3138         wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3139                    station_obj_path);
3140         if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3141                                                wpa_s->ifname, obj_desc)) {
3142                 wpa_printf(MSG_ERROR,
3143                            "Cannot register STA dbus object %s",
3144                            station_obj_path);
3145                 goto err;
3146         }
3147
3148         wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3149         wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3150
3151         return 0;
3152
3153 err:
3154         free_dbus_object_desc(obj_desc);
3155         return -1;
3156 }
3157
3158
3159 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
3160         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3161           (WPADBusMethodHandler) wpas_dbus_handler_scan,
3162           {
3163                   { "args", "a{sv}", ARG_IN },
3164                   END_ARGS
3165           }
3166         },
3167         { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3168           (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3169           {
3170                   { "args", "a{sv}", ARG_OUT },
3171                   END_ARGS
3172           }
3173         },
3174         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3175           (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3176           {
3177                   END_ARGS
3178           }
3179         },
3180         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3181           (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3182           {
3183                   { "args", "a{sv}", ARG_IN },
3184                   { "path", "o", ARG_OUT },
3185                   END_ARGS
3186           }
3187         },
3188         { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3189           (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3190           {
3191                   END_ARGS
3192           }
3193         },
3194         { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3195           (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3196           {
3197                   END_ARGS
3198           }
3199         },
3200         { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3201           (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3202           {
3203                   END_ARGS
3204           }
3205         },
3206         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3207           (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3208           {
3209                   { "path", "o", ARG_IN },
3210                   END_ARGS
3211           }
3212         },
3213         { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3214           (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3215           {
3216                   END_ARGS
3217           }
3218         },
3219         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3220           (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3221           {
3222                   { "path", "o", ARG_IN },
3223                   END_ARGS
3224           }
3225         },
3226         { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3227           (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3228           {
3229                   { "path", "o", ARG_IN },
3230                   { "field", "s", ARG_IN },
3231                   { "value", "s", ARG_IN },
3232                   END_ARGS
3233           }
3234         },
3235 #ifndef CONFIG_NO_CONFIG_BLOBS
3236         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3237           (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3238           {
3239                   { "name", "s", ARG_IN },
3240                   { "data", "ay", ARG_IN },
3241                   END_ARGS
3242           }
3243         },
3244         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3245           (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3246           {
3247                   { "name", "s", ARG_IN },
3248                   { "data", "ay", ARG_OUT },
3249                   END_ARGS
3250           }
3251         },
3252         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3253           (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3254           {
3255                   { "name", "s", ARG_IN },
3256                   END_ARGS
3257           }
3258         },
3259 #endif /* CONFIG_NO_CONFIG_BLOBS */
3260         { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3261           (WPADBusMethodHandler)
3262           wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3263           {
3264                   { "pkcs11_engine_path", "s", ARG_IN },
3265                   { "pkcs11_module_path", "s", ARG_IN },
3266                   END_ARGS
3267           }
3268         },
3269 #ifdef CONFIG_WPS
3270         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
3271           (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3272           {
3273                   { "args", "a{sv}", ARG_IN },
3274                   { "output", "a{sv}", ARG_OUT },
3275                   END_ARGS
3276           }
3277         },
3278         { "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3279           (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3280           {
3281                   END_ARGS
3282           }
3283         },
3284 #endif /* CONFIG_WPS */
3285 #ifdef CONFIG_P2P
3286         { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3287           (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3288           {
3289                   { "args", "a{sv}", ARG_IN },
3290                   END_ARGS
3291           }
3292         },
3293         { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3294           (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3295           {
3296                   END_ARGS
3297           }
3298         },
3299         { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3300           (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3301           {
3302                   { "timeout", "i", ARG_IN },
3303                   END_ARGS
3304           }
3305         },
3306         { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3307           (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3308           {
3309                   { "args", "a{sv}", ARG_IN },
3310                   END_ARGS
3311           }
3312         },
3313         { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3314           (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3315           {
3316                   { "args", "a{sv}", ARG_IN },
3317                   END_ARGS
3318           }
3319         },
3320         { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3321           (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3322           {
3323                   { "peer", "o", ARG_IN },
3324                   { "config_method", "s", ARG_IN },
3325                   END_ARGS
3326           }
3327         },
3328         { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3329           (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3330           {
3331                   { "args", "a{sv}", ARG_IN },
3332                   { "generated_pin", "s", ARG_OUT },
3333                   END_ARGS
3334           }
3335         },
3336         { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3337           (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3338           {
3339                   { "args", "a{sv}", ARG_IN },
3340                   END_ARGS
3341           }
3342         },
3343         { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3344           (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3345           {
3346                   END_ARGS
3347           }
3348         },
3349         { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3350           (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3351           {
3352                   { "args", "a{sv}", ARG_IN },
3353                   END_ARGS
3354           }
3355         },
3356         { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3357           (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3358           {
3359                   END_ARGS
3360           }
3361         },
3362         { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3363           (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3364           {
3365                   { "peer", "o", ARG_IN },
3366                   END_ARGS
3367           }
3368         },
3369         { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3370           (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3371           {
3372                   { "args", "a{sv}", ARG_IN },
3373                   END_ARGS
3374           }
3375         },
3376         { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3377           (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3378           {
3379                   END_ARGS
3380           }
3381         },
3382         { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3383           (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3384           {
3385                   { "args", "a{sv}", ARG_IN },
3386                   END_ARGS
3387           }
3388         },
3389         { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3390           (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3391           {
3392                   { "args", "a{sv}", ARG_IN },
3393                   END_ARGS
3394           }
3395         },
3396         { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3397           (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3398           {
3399                   END_ARGS
3400           }
3401         },
3402         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3403           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3404           {
3405                   { "args", "a{sv}", ARG_IN },
3406                   { "ref", "t", ARG_OUT },
3407                   END_ARGS
3408           }
3409         },
3410         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3411           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3412           {
3413                   { "args", "a{sv}", ARG_IN },
3414                   END_ARGS
3415           }
3416         },
3417         { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3418           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3419           {
3420                   { "args", "t", ARG_IN },
3421                   END_ARGS
3422           }
3423         },
3424         { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3425           (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3426           {
3427                   END_ARGS
3428           }
3429         },
3430         { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3431           (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3432           {
3433                   { "arg", "i", ARG_IN },
3434                   END_ARGS
3435           }
3436         },
3437         { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3438           (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3439           {
3440                   { "args", "a{sv}", ARG_IN },
3441                   { "path", "o", ARG_OUT },
3442                   END_ARGS
3443           }
3444         },
3445         { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3446           (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3447           {
3448                   { "path", "o", ARG_IN },
3449                   END_ARGS
3450           }
3451         },
3452         { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3453           (WPADBusMethodHandler)
3454           wpas_dbus_handler_remove_all_persistent_groups,
3455           {
3456                   END_ARGS
3457           }
3458         },
3459 #endif /* CONFIG_P2P */
3460         { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3461           (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3462           {
3463                   { "age", "u", ARG_IN },
3464                   END_ARGS
3465           }
3466         },
3467 #ifdef CONFIG_AP
3468         { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3469           (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3470           {
3471                   END_ARGS
3472           }
3473         },
3474         { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3475           (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3476           {
3477                   END_ARGS
3478           }
3479         },
3480 #endif /* CONFIG_AP */
3481         { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3482           (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3483           {
3484                   END_ARGS
3485           }
3486         },
3487         { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3488           (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3489           {
3490                   END_ARGS
3491           }
3492         },
3493 #ifdef CONFIG_AUTOSCAN
3494         { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3495           (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3496           {
3497                   { "arg", "s", ARG_IN },
3498                   END_ARGS
3499           }
3500         },
3501 #endif /* CONFIG_AUTOSCAN */
3502 #ifdef CONFIG_TDLS
3503         { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3504           (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3505           {
3506                   { "peer_address", "s", ARG_IN },
3507                   END_ARGS
3508           }
3509         },
3510         { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3511           (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3512           {
3513                   { "peer_address", "s", ARG_IN },
3514                   END_ARGS
3515           }
3516         },
3517         { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3518           (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3519           {
3520                   { "peer_address", "s", ARG_IN },
3521                   { "status", "s", ARG_OUT },
3522                   END_ARGS
3523           }
3524         },
3525         { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3526           (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3527           {
3528                   { "peer_address", "s", ARG_IN },
3529                   END_ARGS
3530           }
3531         },
3532         { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3533           (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3534           {
3535                   { "args", "a{sv}", ARG_IN },
3536                   END_ARGS
3537           }
3538         },
3539         { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3540           (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3541           {
3542                   { "peer_address", "s", ARG_IN },
3543                   END_ARGS
3544           }
3545         },
3546 #endif /* CONFIG_TDLS */
3547         { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3548           (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3549           {
3550                   { "frame_id", "i", ARG_IN },
3551                   { "ielems", "ay", ARG_IN },
3552                   END_ARGS
3553           }
3554         },
3555         { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3556           (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3557           {
3558                   { "frame_id", "i", ARG_IN },
3559                   { "ielems", "ay", ARG_OUT },
3560                   END_ARGS
3561           }
3562         },
3563         { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3564           (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3565           {
3566                   { "frame_id", "i", ARG_IN },
3567                   { "ielems", "ay", ARG_IN },
3568                   END_ARGS
3569           }
3570         },
3571 #ifndef CONFIG_NO_CONFIG_WRITE
3572         { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3573           (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3574           {
3575                   END_ARGS
3576           }
3577         },
3578 #endif /* CONFIG_NO_CONFIG_WRITE */
3579         { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3580           (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3581           {
3582                   END_ARGS
3583           }
3584         },
3585         { NULL, NULL, NULL, { END_ARGS } }
3586 };
3587
3588 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3589         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3590           wpas_dbus_getter_capabilities,
3591           NULL,
3592           NULL
3593         },
3594         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3595           wpas_dbus_getter_state,
3596           NULL,
3597           NULL
3598         },
3599         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3600           wpas_dbus_getter_scanning,
3601           NULL,
3602           NULL
3603         },
3604         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3605           wpas_dbus_getter_ap_scan,
3606           wpas_dbus_setter_ap_scan,
3607           NULL
3608         },
3609         { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3610           wpas_dbus_getter_bss_expire_age,
3611           wpas_dbus_setter_bss_expire_age,
3612           NULL
3613         },
3614         { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3615           wpas_dbus_getter_bss_expire_count,
3616           wpas_dbus_setter_bss_expire_count,
3617           NULL
3618         },
3619         { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3620           wpas_dbus_getter_country,
3621           wpas_dbus_setter_country,
3622           NULL
3623         },
3624         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3625           wpas_dbus_getter_ifname,
3626           NULL,
3627           NULL
3628         },
3629         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3630           wpas_dbus_getter_driver,
3631           NULL,
3632           NULL
3633         },
3634         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3635           wpas_dbus_getter_bridge_ifname,
3636           NULL,
3637           NULL
3638         },
3639         { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3640           wpas_dbus_getter_config_file,
3641           NULL,
3642           NULL
3643         },
3644         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3645           wpas_dbus_getter_current_bss,
3646           NULL,
3647           NULL
3648         },
3649         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3650           wpas_dbus_getter_current_network,
3651           NULL,
3652           NULL
3653         },
3654         { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3655           wpas_dbus_getter_current_auth_mode,
3656           NULL,
3657           NULL
3658         },
3659         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3660           wpas_dbus_getter_blobs,
3661           NULL,
3662           NULL
3663         },
3664         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3665           wpas_dbus_getter_bsss,
3666           NULL,
3667           NULL
3668         },
3669         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3670           wpas_dbus_getter_networks,
3671           NULL,
3672           NULL
3673         },
3674         { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3675           wpas_dbus_getter_fast_reauth,
3676           wpas_dbus_setter_fast_reauth,
3677           NULL
3678         },
3679         { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3680           wpas_dbus_getter_scan_interval,
3681           wpas_dbus_setter_scan_interval,
3682           NULL
3683         },
3684         { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3685           wpas_dbus_getter_pkcs11_engine_path,
3686           NULL,
3687           NULL
3688         },
3689         { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3690           wpas_dbus_getter_pkcs11_module_path,
3691           NULL,
3692           NULL
3693         },
3694 #ifdef CONFIG_WPS
3695         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
3696           wpas_dbus_getter_process_credentials,
3697           wpas_dbus_setter_process_credentials,
3698           NULL
3699         },
3700         { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
3701           wpas_dbus_getter_config_methods,
3702           wpas_dbus_setter_config_methods,
3703           NULL
3704         },
3705         {
3706           "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3707           wpas_dbus_getter_wps_device_name,
3708           wpas_dbus_setter_wps_device_name,
3709           NULL
3710         },
3711         {
3712           "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
3713           wpas_dbus_getter_wps_manufacturer,
3714           wpas_dbus_setter_wps_manufacturer,
3715           NULL
3716         },
3717         {
3718           "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3719           wpas_dbus_getter_wps_device_model_name,
3720           wpas_dbus_setter_wps_device_model_name,
3721           NULL
3722         },
3723         {
3724           "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3725           wpas_dbus_getter_wps_device_model_number,
3726           wpas_dbus_setter_wps_device_model_number,
3727           NULL
3728         },
3729         {
3730           "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3731           wpas_dbus_getter_wps_device_serial_number,
3732           wpas_dbus_setter_wps_device_serial_number,
3733           NULL
3734         },
3735         {
3736           "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
3737           wpas_dbus_getter_wps_device_device_type,
3738           wpas_dbus_setter_wps_device_device_type,
3739           NULL
3740         },
3741 #endif /* CONFIG_WPS */
3742 #ifdef CONFIG_P2P
3743         { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
3744           wpas_dbus_getter_p2p_device_config,
3745           wpas_dbus_setter_p2p_device_config,
3746           NULL
3747         },
3748         { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3749           wpas_dbus_getter_p2p_peers,
3750           NULL,
3751           NULL
3752         },
3753         { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
3754           wpas_dbus_getter_p2p_role,
3755           NULL,
3756           NULL
3757         },
3758         { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3759           wpas_dbus_getter_p2p_group,
3760           NULL,
3761           NULL
3762         },
3763         { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3764           wpas_dbus_getter_p2p_peergo,
3765           NULL,
3766           NULL
3767         },
3768         { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3769           wpas_dbus_getter_persistent_groups,
3770           NULL,
3771           NULL
3772         },
3773 #endif /* CONFIG_P2P */
3774         { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3775           wpas_dbus_getter_disconnect_reason,
3776           NULL,
3777           NULL
3778         },
3779         { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3780           wpas_dbus_getter_auth_status_code,
3781           NULL,
3782           NULL
3783         },
3784         { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3785           wpas_dbus_getter_assoc_status_code,
3786           NULL,
3787           NULL
3788         },
3789 #ifdef CONFIG_MESH
3790         { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
3791           wpas_dbus_getter_mesh_peers,
3792           NULL,
3793           NULL
3794         },
3795         { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
3796           wpas_dbus_getter_mesh_group,
3797           NULL,
3798           NULL
3799         },
3800 #endif /* CONFIG_MESH */
3801         { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3802           wpas_dbus_getter_stas,
3803           NULL,
3804           NULL
3805         },
3806         { NULL, NULL, NULL, NULL, NULL, NULL }
3807 };
3808
3809 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
3810         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
3811           {
3812                   { "success", "b", ARG_OUT },
3813                   END_ARGS
3814           }
3815         },
3816         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3817           {
3818                   { "path", "o", ARG_OUT },
3819                   { "properties", "a{sv}", ARG_OUT },
3820                   END_ARGS
3821           }
3822         },
3823         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3824           {
3825                   { "path", "o", ARG_OUT },
3826                   END_ARGS
3827           }
3828         },
3829         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3830           {
3831                   { "name", "s", ARG_OUT },
3832                   END_ARGS
3833           }
3834         },
3835         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3836           {
3837                   { "name", "s", ARG_OUT },
3838                   END_ARGS
3839           }
3840         },
3841         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3842           {
3843                   { "path", "o", ARG_OUT },
3844                   { "properties", "a{sv}", ARG_OUT },
3845                   END_ARGS
3846           }
3847         },
3848         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3849           {
3850                   { "path", "o", ARG_OUT },
3851                   END_ARGS
3852           }
3853         },
3854         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
3855           {
3856                   { "path", "o", ARG_OUT },
3857                   END_ARGS
3858           }
3859         },
3860         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3861         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
3862           {
3863                   { "properties", "a{sv}", ARG_OUT },
3864                   END_ARGS
3865           }
3866         },
3867 #ifdef CONFIG_WPS
3868         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
3869           {
3870                   { "name", "s", ARG_OUT },
3871                   { "args", "a{sv}", ARG_OUT },
3872                   END_ARGS
3873           }
3874         },
3875         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
3876           {
3877                   { "credentials", "a{sv}", ARG_OUT },
3878                   END_ARGS
3879           }
3880         },
3881         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3882         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
3883           {
3884                   { "properties", "a{sv}", ARG_OUT },
3885                   END_ARGS
3886           }
3887         },
3888 #endif /* CONFIG_WPS */
3889 #ifdef CONFIG_P2P
3890         { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3891           {
3892                   { "path", "o", ARG_OUT },
3893                   END_ARGS
3894           }
3895         },
3896         { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3897           {
3898                   { "path", "o", ARG_OUT },
3899                   { "properties", "a{sv}", ARG_OUT },
3900                   END_ARGS
3901           }
3902         },
3903         { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3904           {
3905                   { "path", "o", ARG_OUT },
3906                   END_ARGS
3907           }
3908         },
3909         { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3910           {
3911                   END_ARGS
3912           }
3913         },
3914         { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3915           {
3916                   { "peer_object", "o", ARG_OUT },
3917                   { "pin", "s", ARG_OUT },
3918                   END_ARGS
3919           }
3920         },
3921         { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3922           {
3923                   { "peer_object", "o", ARG_OUT },
3924                   { "pin", "s", ARG_OUT },
3925                   END_ARGS
3926           }
3927         },
3928         { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3929           {
3930                   { "peer_object", "o", ARG_OUT },
3931                   END_ARGS
3932           }
3933         },
3934         { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3935           {
3936                   { "peer_object", "o", ARG_OUT },
3937                   END_ARGS
3938           }
3939         },
3940         { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3941           {
3942                   { "peer_object", "o", ARG_OUT },
3943                   END_ARGS
3944           }
3945         },
3946         { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3947           {
3948                   { "peer_object", "o", ARG_OUT },
3949                   END_ARGS
3950           }
3951         },
3952         { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3953           {
3954                   { "peer_object", "o", ARG_OUT },
3955                   { "status", "i", ARG_OUT },
3956                   END_ARGS
3957           }
3958         },
3959         { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3960           {
3961                   { "properties", "a{sv}", ARG_OUT },
3962                   END_ARGS
3963           }
3964         },
3965         { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3966           {
3967                   { "reason", "s", ARG_OUT },
3968                   END_ARGS
3969           }
3970         },
3971         { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3972           {
3973                   { "properties", "a{sv}", ARG_OUT },
3974                   END_ARGS
3975           }
3976         },
3977         { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3978           {
3979                   { "properties", "a{sv}", ARG_OUT },
3980                   END_ARGS
3981           }
3982         },
3983         { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3984           {
3985                   { "path", "o", ARG_OUT },
3986                   { "dev_passwd_id", "q", ARG_OUT },
3987                   { "device_go_intent", "y", ARG_OUT },
3988                   END_ARGS
3989           }
3990         },
3991         { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3992           {
3993                   { "invite_result", "a{sv}", ARG_OUT },
3994                   END_ARGS
3995           }
3996         },
3997         { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3998           {
3999                   { "properties", "a{sv}", ARG_OUT },
4000                   END_ARGS
4001           }
4002         },
4003         { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4004           {
4005                   { "sd_request", "a{sv}", ARG_OUT },
4006                   END_ARGS
4007           }
4008         },
4009         { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4010           {
4011                   { "sd_response", "a{sv}", ARG_OUT },
4012                   END_ARGS
4013           }
4014         },
4015         { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4016           {
4017                   { "path", "o", ARG_OUT },
4018                   { "properties", "a{sv}", ARG_OUT },
4019                   END_ARGS
4020           }
4021         },
4022         { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4023           {
4024                   { "path", "o", ARG_OUT },
4025                   END_ARGS
4026           }
4027         },
4028         { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4029           {
4030                   { "name", "s", ARG_OUT },
4031                   { "args", "a{sv}", ARG_OUT },
4032                   END_ARGS
4033           }
4034         },
4035         { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4036           {
4037                   { "properties", "a{sv}", ARG_OUT },
4038                   END_ARGS
4039           }
4040         },
4041 #endif /* CONFIG_P2P */
4042 #ifdef CONFIG_AP
4043         { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4044           {
4045                   { "args", "a{sv}", ARG_OUT },
4046                   END_ARGS
4047           }
4048         },
4049 #endif /* CONFIG_AP */
4050         { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4051           {
4052                   { "certification", "a{sv}", ARG_OUT },
4053                   END_ARGS
4054           }
4055         },
4056         { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4057           {
4058                   { "status", "s", ARG_OUT },
4059                   { "parameter", "s", ARG_OUT },
4060                   END_ARGS
4061           }
4062         },
4063         { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4064           {
4065                   { "name", "s", ARG_OUT },
4066                   END_ARGS
4067           }
4068         },
4069         { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4070           {
4071                   { "name", "s", ARG_OUT },
4072                   END_ARGS
4073           }
4074         },
4075         { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4076           {
4077                   { "path", "o", ARG_OUT },
4078                   { "properties", "a{sv}", ARG_OUT },
4079                   END_ARGS
4080           }
4081         },
4082         { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4083           {
4084                   { "path", "o", ARG_OUT },
4085                   END_ARGS
4086           }
4087         },
4088         { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4089           {
4090                   { "path", "o", ARG_OUT },
4091                   { "field", "s", ARG_OUT },
4092                   { "text", "s", ARG_OUT },
4093                   END_ARGS
4094           }
4095         },
4096 #ifdef CONFIG_MESH
4097         { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4098           {
4099                   { "args", "a{sv}", ARG_OUT },
4100                   END_ARGS
4101           }
4102         },
4103         { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4104           {
4105                   { "args", "a{sv}", ARG_OUT },
4106                   END_ARGS
4107           }
4108         },
4109         { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4110           {
4111                   { "args", "a{sv}", ARG_OUT },
4112                   END_ARGS
4113           }
4114         },
4115         { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4116           {
4117                   { "args", "a{sv}", ARG_OUT },
4118                   END_ARGS
4119           }
4120         },
4121 #endif /* CONFIG_MESH */
4122         { NULL, NULL, { END_ARGS } }
4123 };
4124
4125
4126 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4127 {
4128         size_t all_size;
4129         unsigned int i, j, count, num_const, num_globals;
4130         const char *global_name;
4131         static const char * const ignored_globals[] = {
4132                 "bss_expiration_age", "bss_expiration_scan_count",
4133                 "ap_scan", "country", "fast_reauth",
4134                 "pkcs11_engine_path", "pkcs11_module_path"
4135         };
4136
4137         /* wpas_dbus_interface_properties terminates with a NULL element */
4138         num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4139
4140         num_globals = wpa_config_get_num_global_field_names();
4141         priv->globals_start = num_const;
4142
4143         /* allocate enough for all properties + terminating NULL element */
4144         all_size = (num_globals + num_const + 1) *
4145                 sizeof(wpas_dbus_interface_properties[0]);
4146         priv->all_interface_properties = os_zalloc(all_size);
4147         if (!priv->all_interface_properties) {
4148                 wpa_printf(MSG_ERROR,
4149                            "dbus: Not enough memory for interface properties");
4150                 return -1;
4151         }
4152
4153         /* Copy constant interface properties to the start of the array */
4154         os_memcpy(priv->all_interface_properties,
4155                   wpas_dbus_interface_properties,
4156                   sizeof(wpas_dbus_interface_properties));
4157
4158         /* Dynamically construct interface global properties */
4159         for (i = 0, count = num_const; i < num_globals; i++) {
4160                 struct wpa_dbus_property_desc *desc;
4161                 int no_var = 0;
4162
4163                 /* ignore globals that are actually just methods */
4164                 global_name = wpa_config_get_global_field_name(i, &no_var);
4165                 if (no_var)
4166                         continue;
4167                 /* Ignore fields already explicitly exposed */
4168                 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4169                         if (os_strcmp(global_name, ignored_globals[j]) == 0)
4170                                 break;
4171                 }
4172                 if (j < ARRAY_SIZE(ignored_globals))
4173                         continue;
4174
4175                 desc = &priv->all_interface_properties[count++];
4176                 desc->dbus_property = uscore_to_dbus(global_name);
4177                 if (!desc->dbus_property) {
4178                         wpa_printf(MSG_ERROR,
4179                                    "dbus: Not enough memory for D-Bus property name");
4180                         goto error;
4181                 }
4182                 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4183                 desc->type = "s";
4184                 desc->getter = wpas_dbus_getter_iface_global;
4185                 desc->setter = wpas_dbus_setter_iface_global;
4186                 desc->data = global_name;
4187         }
4188
4189         return 0;
4190
4191 error:
4192         wpa_dbus_ctrl_iface_props_deinit(priv);
4193         return -1;
4194 }
4195
4196
4197 /**
4198  * wpas_dbus_register_interface - Register an interface with D-Bus
4199  * @wpa_s: wpa_supplicant interface structure
4200  * Returns: 0 on success, -1 on failure
4201  */
4202 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4203 {
4204         struct wpa_dbus_object_desc *obj_desc = NULL;
4205         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4206         int next;
4207
4208         /* Do nothing if the control interface is not turned on */
4209         if (ctrl_iface == NULL)
4210                 return 0;
4211
4212         /* Create and set the interface's object path */
4213         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4214         if (wpa_s->dbus_new_path == NULL)
4215                 return -1;
4216         next = ctrl_iface->next_objid++;
4217         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4218                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4219                     next);
4220
4221         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4222         if (!obj_desc) {
4223                 wpa_printf(MSG_ERROR,
4224                            "Not enough memory to create object description");
4225                 goto err;
4226         }
4227
4228         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4229                            ctrl_iface->all_interface_properties,
4230                            wpas_dbus_interface_signals);
4231
4232         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4233                    wpa_s->dbus_new_path);
4234         if (wpa_dbus_register_object_per_iface(ctrl_iface,
4235                                                wpa_s->dbus_new_path,
4236                                                wpa_s->ifname, obj_desc))
4237                 goto err;
4238
4239         wpas_dbus_signal_interface_added(wpa_s);
4240
4241         return 0;
4242
4243 err:
4244         os_free(wpa_s->dbus_new_path);
4245         wpa_s->dbus_new_path = NULL;
4246         free_dbus_object_desc(obj_desc);
4247         return -1;
4248 }
4249
4250
4251 /**
4252  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4253  * @wpa_s: wpa_supplicant interface structure
4254  * Returns: 0 on success, -1 on failure
4255  */
4256 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4257 {
4258         struct wpas_dbus_priv *ctrl_iface;
4259
4260         /* Do nothing if the control interface is not turned on */
4261         if (wpa_s == NULL || wpa_s->global == NULL)
4262                 return 0;
4263         ctrl_iface = wpa_s->global->dbus;
4264         if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4265                 return 0;
4266
4267         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4268                    wpa_s->dbus_new_path);
4269
4270 #ifdef CONFIG_AP
4271         if (wpa_s->preq_notify_peer) {
4272                 wpas_dbus_unsubscribe_noc(ctrl_iface);
4273                 os_free(wpa_s->preq_notify_peer);
4274                 wpa_s->preq_notify_peer = NULL;
4275         }
4276 #endif /* CONFIG_AP */
4277
4278         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4279                                                  wpa_s->dbus_new_path))
4280                 return -1;
4281
4282         wpas_dbus_signal_interface_removed(wpa_s);
4283
4284         os_free(wpa_s->dbus_new_path);
4285         wpa_s->dbus_new_path = NULL;
4286
4287         return 0;
4288 }
4289
4290 #ifdef CONFIG_P2P
4291
4292 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4293         { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4294           wpas_dbus_getter_p2p_peer_device_name,
4295           NULL,
4296           NULL
4297         },
4298         { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4299           wpas_dbus_getter_p2p_peer_manufacturer,
4300           NULL,
4301           NULL
4302         },
4303         { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4304           wpas_dbus_getter_p2p_peer_modelname,
4305           NULL,
4306           NULL
4307         },
4308         { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4309           wpas_dbus_getter_p2p_peer_modelnumber,
4310           NULL,
4311           NULL
4312         },
4313         { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4314           wpas_dbus_getter_p2p_peer_serialnumber,
4315           NULL,
4316           NULL
4317         },
4318         { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4319           wpas_dbus_getter_p2p_peer_primary_device_type,
4320           NULL,
4321           NULL
4322         },
4323         { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4324           wpas_dbus_getter_p2p_peer_config_method,
4325           NULL,
4326           NULL
4327         },
4328         { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4329           wpas_dbus_getter_p2p_peer_level,
4330           NULL,
4331           NULL
4332         },
4333         { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4334           wpas_dbus_getter_p2p_peer_device_capability,
4335           NULL,
4336           NULL
4337         },
4338         { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4339           wpas_dbus_getter_p2p_peer_group_capability,
4340           NULL,
4341           NULL
4342         },
4343         { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4344           wpas_dbus_getter_p2p_peer_secondary_device_types,
4345           NULL,
4346           NULL
4347         },
4348         { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4349           wpas_dbus_getter_p2p_peer_vendor_extension,
4350           NULL,
4351           NULL
4352         },
4353         { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4354           wpas_dbus_getter_p2p_peer_ies,
4355           NULL,
4356           NULL
4357         },
4358         { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4359           wpas_dbus_getter_p2p_peer_device_address,
4360           NULL,
4361           NULL
4362         },
4363         { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4364           wpas_dbus_getter_p2p_peer_groups,
4365           NULL,
4366           NULL
4367         },
4368         { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4369           wpas_dbus_getter_p2p_peer_vsie,
4370           NULL,
4371           NULL
4372         },
4373         { NULL, NULL, NULL, NULL, NULL, NULL }
4374 };
4375
4376 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4377         /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4378         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4379           {
4380                   { "properties", "a{sv}", ARG_OUT },
4381                   END_ARGS
4382           }
4383         },
4384         { NULL, NULL, { END_ARGS } }
4385 };
4386
4387 /**
4388  * wpas_dbus_signal_peer - Send a peer related event signal
4389  * @wpa_s: %wpa_supplicant network interface data
4390  * @dev: peer device object
4391  * @interface: name of the interface emitting this signal.
4392  *      In case of peer objects, it would be emitted by either
4393  *      the "interface object" or by "peer objects"
4394  * @sig_name: signal name - DeviceFound
4395  * @properties: Whether to add a second argument with object properties
4396  *
4397  * Notify listeners about event related with p2p peer device
4398  */
4399 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4400                                   const u8 *dev_addr, const char *interface,
4401                                   const char *sig_name, dbus_bool_t properties)
4402 {
4403         struct wpas_dbus_priv *iface;
4404         DBusMessage *msg;
4405         DBusMessageIter iter;
4406         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4407
4408         if (wpa_s->p2p_mgmt)
4409                 wpa_s = wpa_s->parent;
4410
4411         iface = wpa_s->global->dbus;
4412
4413         /* Do nothing if the control interface is not turned on */
4414         if (iface == NULL || !wpa_s->dbus_new_path)
4415                 return;
4416
4417         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4418                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4419                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
4420
4421         msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4422                                       sig_name);
4423         if (msg == NULL)
4424                 return;
4425
4426         dbus_message_iter_init_append(msg, &iter);
4427         path = peer_obj_path;
4428         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4429                                             &path) ||
4430             (properties && !wpa_dbus_get_object_properties(
4431                     iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4432                     &iter)))
4433                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4434         else
4435                 dbus_connection_send(iface->con, msg, NULL);
4436
4437         dbus_message_unref(msg);
4438 }
4439
4440
4441 /**
4442  * wpas_dbus_signal_peer_found - Send a peer found signal
4443  * @wpa_s: %wpa_supplicant network interface data
4444  * @dev_addr: Peer P2P Device Address
4445  *
4446  * Notify listeners about find a p2p peer device found
4447  */
4448 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4449                                         const u8 *dev_addr)
4450 {
4451         wpas_dbus_signal_peer(wpa_s, dev_addr,
4452                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4453                               "DeviceFound", FALSE);
4454
4455         wpas_dbus_signal_peer(wpa_s, dev_addr,
4456                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4457                               "DeviceFoundProperties", TRUE);
4458 }
4459
4460 /**
4461  * wpas_dbus_signal_peer_lost - Send a peer lost signal
4462  * @wpa_s: %wpa_supplicant network interface data
4463  * @dev_addr: Peer P2P Device Address
4464  *
4465  * Notify listeners about lost a p2p peer device
4466  */
4467 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4468                                        const u8 *dev_addr)
4469 {
4470         wpas_dbus_signal_peer(wpa_s, dev_addr,
4471                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4472                               "DeviceLost", FALSE);
4473 }
4474
4475 /**
4476  * wpas_dbus_register_peer - Register a discovered peer object with dbus
4477  * @wpa_s: wpa_supplicant interface structure
4478  * @dev_addr: P2P Device Address of the peer
4479  * Returns: 0 on success, -1 on failure
4480  *
4481  * Registers network representing object with dbus
4482  */
4483 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4484 {
4485         struct wpas_dbus_priv *ctrl_iface;
4486         struct wpa_dbus_object_desc *obj_desc;
4487         struct peer_handler_args *arg;
4488         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4489
4490         /* Do nothing if the control interface is not turned on */
4491         if (wpa_s == NULL || wpa_s->global == NULL)
4492                 return 0;
4493
4494         ctrl_iface = wpa_s->global->dbus;
4495         if (ctrl_iface == NULL)
4496                 return 0;
4497
4498         wpa_s = wpa_s->parent->parent;
4499         if (!wpa_s->dbus_new_path)
4500                 return 0;
4501
4502         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4503                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4504                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
4505
4506         wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4507                    peer_obj_path);
4508         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4509         if (!obj_desc) {
4510                 wpa_printf(MSG_ERROR,
4511                            "Not enough memory to create object description");
4512                 goto err;
4513         }
4514
4515         /* allocate memory for handlers arguments */
4516         arg = os_zalloc(sizeof(struct peer_handler_args));
4517         if (!arg) {
4518                 wpa_printf(MSG_ERROR,
4519                            "Not enough memory to create arguments for method");
4520                 goto err;
4521         }
4522
4523         arg->wpa_s = wpa_s;
4524         os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4525
4526         wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4527                            NULL,
4528                            wpas_dbus_p2p_peer_properties,
4529                            wpas_dbus_p2p_peer_signals);
4530
4531         if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4532                                                wpa_s->ifname, obj_desc))
4533                 goto err;
4534
4535         return 0;
4536
4537 err:
4538         free_dbus_object_desc(obj_desc);
4539         return -1;
4540 }
4541
4542 /**
4543  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4544  * @wpa_s: wpa_supplicant interface structure
4545  * @dev_addr: p2p device addr
4546  * Returns: 0 on success, -1 on failure
4547  *
4548  * Registers network representing object with dbus
4549  */
4550 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4551                                   const u8 *dev_addr)
4552 {
4553         struct wpas_dbus_priv *ctrl_iface;
4554         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4555         int ret;
4556
4557         /* Do nothing if the control interface is not turned on */
4558         if (wpa_s == NULL || wpa_s->global == NULL)
4559                 return 0;
4560
4561         wpa_s = wpa_s->parent->parent;
4562         if (!wpa_s->dbus_new_path)
4563                 return 0;
4564
4565         ctrl_iface = wpa_s->global->dbus;
4566         if (ctrl_iface == NULL)
4567                 return 0;
4568
4569         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4570                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4571                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
4572
4573         wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
4574                    peer_obj_path);
4575         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
4576
4577         return ret;
4578 }
4579
4580
4581 /**
4582  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
4583  * @wpa_s: %wpa_supplicant network interface data
4584  *
4585  * Notify listeners about P2P Find stopped
4586  */
4587 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
4588 {
4589         struct wpas_dbus_priv *iface;
4590         DBusMessage *msg;
4591
4592         iface = wpa_s->global->dbus;
4593
4594         /* Do nothing if the control interface is not turned on */
4595         if (iface == NULL)
4596                 return;
4597
4598         if (wpa_s->p2p_mgmt)
4599                 wpa_s = wpa_s->parent;
4600
4601         if (!wpa_s->dbus_new_path)
4602                 return;
4603
4604         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4605                                       WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4606                                       "FindStopped");
4607         if (msg == NULL)
4608                 return;
4609
4610         dbus_connection_send(iface->con, msg, NULL);
4611
4612         dbus_message_unref(msg);
4613 }
4614
4615
4616 /**
4617  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
4618  * @wpa_s: %wpa_supplicant network interface data
4619  * @dev_addr: P2P Device Address
4620  *
4621  * Notify listeners about peer Groups property changes.
4622  */
4623 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
4624                                           const u8 *dev_addr)
4625 {
4626         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4627
4628         if (wpa_s->p2p_mgmt)
4629                 wpa_s = wpa_s->parent;
4630
4631         if (!wpa_s->dbus_new_path)
4632                 return;
4633         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4634                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4635                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
4636
4637         wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
4638                                        WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
4639 }
4640
4641
4642 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
4643         { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
4644           wpas_dbus_getter_p2p_group_members,
4645           NULL,
4646           NULL
4647         },
4648         { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
4649           wpas_dbus_getter_p2p_group,
4650           NULL,
4651           NULL
4652         },
4653         { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4654           wpas_dbus_getter_p2p_role,
4655           NULL,
4656           NULL
4657         },
4658         { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4659           wpas_dbus_getter_p2p_group_ssid,
4660           NULL,
4661           NULL
4662         },
4663         { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4664           wpas_dbus_getter_p2p_group_bssid,
4665           NULL,
4666           NULL
4667         },
4668         { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
4669           wpas_dbus_getter_p2p_group_frequency,
4670           NULL,
4671           NULL
4672         },
4673         { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4674           wpas_dbus_getter_p2p_group_passphrase,
4675           NULL,
4676           NULL
4677         },
4678         { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4679           wpas_dbus_getter_p2p_group_psk,
4680           NULL,
4681           NULL
4682         },
4683         { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
4684           wpas_dbus_getter_p2p_group_vendor_ext,
4685           wpas_dbus_setter_p2p_group_vendor_ext,
4686           NULL
4687         },
4688         { NULL, NULL, NULL, NULL, NULL, NULL }
4689 };
4690
4691 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
4692         { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4693           {
4694                   { "peer", "o", ARG_OUT },
4695                   END_ARGS
4696           }
4697         },
4698         { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4699           {
4700                   { "peer", "o", ARG_OUT },
4701                   END_ARGS
4702           }
4703         },
4704         { NULL, NULL, { END_ARGS } }
4705 };
4706
4707 /**
4708  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
4709  * @wpa_s: wpa_supplicant interface structure
4710  * @ssid: SSID struct
4711  * Returns: 0 on success, -1 on failure
4712  *
4713  * Registers p2p group representing object with dbus
4714  */
4715 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
4716                                   struct wpa_ssid *ssid)
4717 {
4718         struct wpas_dbus_priv *ctrl_iface;
4719         struct wpa_dbus_object_desc *obj_desc;
4720         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4721
4722         /* Do nothing if the control interface is not turned on */
4723         if (wpa_s == NULL || wpa_s->global == NULL)
4724                 return;
4725
4726         ctrl_iface = wpa_s->global->dbus;
4727         if (ctrl_iface == NULL)
4728                 return;
4729
4730         if (wpa_s->dbus_groupobj_path) {
4731                 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
4732                            __func__, wpa_s->dbus_groupobj_path);
4733                 return;
4734         }
4735
4736         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
4737                 return;
4738
4739         wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
4740         if (wpa_s->dbus_groupobj_path == NULL)
4741                 return;
4742
4743         wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
4744                    group_obj_path);
4745         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4746         if (!obj_desc) {
4747                 wpa_printf(MSG_ERROR,
4748                            "Not enough memory to create object description");
4749                 goto err;
4750         }
4751
4752         wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
4753                            wpas_dbus_p2p_group_properties,
4754                            wpas_dbus_p2p_group_signals);
4755
4756         if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
4757                                                wpa_s->ifname, obj_desc))
4758                 goto err;
4759
4760         return;
4761
4762 err:
4763         if (wpa_s->dbus_groupobj_path) {
4764                 os_free(wpa_s->dbus_groupobj_path);
4765                 wpa_s->dbus_groupobj_path = NULL;
4766         }
4767
4768         free_dbus_object_desc(obj_desc);
4769 }
4770
4771 /**
4772  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
4773  * @wpa_s: wpa_supplicant interface structure
4774  * @ssid: network name of the p2p group started
4775  */
4776 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
4777                                     const struct wpa_ssid *ssid)
4778 {
4779         struct wpas_dbus_priv *ctrl_iface;
4780
4781         /* Do nothing if the control interface is not turned on */
4782         if (wpa_s == NULL || wpa_s->global == NULL)
4783                 return;
4784
4785         if (wpa_s->p2p_mgmt)
4786                 wpa_s = wpa_s->parent;
4787
4788         ctrl_iface = wpa_s->global->dbus;
4789         if (ctrl_iface == NULL)
4790                 return;
4791
4792         if (!wpa_s->dbus_groupobj_path) {
4793                 wpa_printf(MSG_DEBUG,
4794                            "%s: Group object '%s' already unregistered",
4795                            __func__, wpa_s->dbus_groupobj_path);
4796                 return;
4797         }
4798
4799         peer_groups_changed(wpa_s);
4800
4801         wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
4802                    wpa_s->dbus_groupobj_path);
4803
4804         wpa_dbus_unregister_object_per_iface(ctrl_iface,
4805                                              wpa_s->dbus_groupobj_path);
4806
4807         os_free(wpa_s->dbus_groupobj_path);
4808         wpa_s->dbus_groupobj_path = NULL;
4809 }
4810
4811 static const struct wpa_dbus_property_desc
4812         wpas_dbus_persistent_group_properties[] = {
4813         { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
4814           wpas_dbus_getter_persistent_group_properties,
4815           wpas_dbus_setter_persistent_group_properties,
4816           NULL
4817         },
4818         { NULL, NULL, NULL, NULL, NULL, NULL }
4819 };
4820
4821 /* No signals intended for persistent group objects */
4822
4823 /**
4824  * wpas_dbus_register_persistent_group - Register a configured(saved)
4825  *      persistent group with dbus
4826  * @wpa_s: wpa_supplicant interface structure
4827  * @ssid: persistent group (still represented as a network within wpa)
4828  *        configuration data
4829  * Returns: 0 on success, -1 on failure
4830  *
4831  * Registers a persistent group representing object with dbus.
4832  */
4833 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
4834                                         struct wpa_ssid *ssid)
4835 {
4836         struct wpas_dbus_priv *ctrl_iface;
4837         struct wpa_dbus_object_desc *obj_desc;
4838         struct network_handler_args *arg;
4839         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4840
4841         /* Do nothing if the control interface is not turned on */
4842         if (wpa_s == NULL || wpa_s->global == NULL)
4843                 return 0;
4844         wpa_s = wpa_s->parent->parent;
4845         if (!wpa_s->dbus_new_path)
4846                 return 0;
4847
4848         /* Make sure ssid is a persistent group */
4849         if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
4850                 return -1; /* should we return w/o complaining? */
4851
4852         if (wpa_s->p2p_mgmt)
4853                 wpa_s = wpa_s->parent;
4854
4855         ctrl_iface = wpa_s->global->dbus;
4856         if (ctrl_iface == NULL)
4857                 return 0;
4858
4859         /*
4860          * Intentionally not coming up with different numbering scheme
4861          * for persistent groups.
4862          */
4863         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4864                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4865                     wpa_s->dbus_new_path, ssid->id);
4866
4867         wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
4868                    pgrp_obj_path);
4869         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4870         if (!obj_desc) {
4871                 wpa_printf(MSG_ERROR,
4872                            "dbus: Not enough memory to create object description");
4873                 goto err;
4874         }
4875
4876         /*
4877          * Reusing the same context structure as that for networks
4878          * since these are represented using same data structure.
4879          */
4880         /* allocate memory for handlers arguments */
4881         arg = os_zalloc(sizeof(struct network_handler_args));
4882         if (!arg) {
4883                 wpa_printf(MSG_ERROR,
4884                            "dbus: Not enough memory to create arguments for method");
4885                 goto err;
4886         }
4887
4888         arg->wpa_s = wpa_s;
4889         arg->ssid = ssid;
4890
4891         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
4892                            wpas_dbus_persistent_group_properties,
4893                            NULL);
4894
4895         if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
4896                                                wpa_s->ifname, obj_desc))
4897                 goto err;
4898
4899         wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
4900
4901         return 0;
4902
4903 err:
4904         free_dbus_object_desc(obj_desc);
4905         return -1;
4906 }
4907
4908
4909 /**
4910  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
4911  *      from dbus
4912  * @wpa_s: wpa_supplicant interface structure
4913  * @nid: network id
4914  * Returns: 0 on success, -1 on failure
4915  *
4916  * Unregisters persistent group representing object from dbus
4917  *
4918  * NOTE: There is a slight issue with the semantics here. While the
4919  * implementation simply means the persistent group is unloaded from memory,
4920  * it should not get interpreted as the group is actually being erased/removed
4921  * from persistent storage as well.
4922  */
4923 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
4924                                           int nid)
4925 {
4926         struct wpas_dbus_priv *ctrl_iface;
4927         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4928         int ret;
4929
4930         /* Do nothing if the control interface is not turned on */
4931         if (wpa_s == NULL || wpa_s->global == NULL)
4932                 return 0;
4933
4934         wpa_s = wpa_s->parent->parent;
4935
4936         ctrl_iface = wpa_s->global->dbus;
4937         if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
4938                 return 0;
4939
4940         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4941                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4942                     wpa_s->dbus_new_path, nid);
4943
4944         wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
4945                    pgrp_obj_path);
4946         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
4947
4948         if (!ret)
4949                 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
4950
4951         return ret;
4952 }
4953
4954 #endif /* CONFIG_P2P */