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