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