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