OSDN Git Service

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