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