Fix D-Bus build without CONFIG_P2P=y
[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         { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2637           {
2638                   { "name", "s", ARG_OUT },
2639                   { "args", "a{sv}", ARG_OUT },
2640                   END_ARGS
2641           }
2642         },
2643 #endif /* CONFIG_P2P */
2644         { NULL, NULL, { END_ARGS } }
2645 };
2646
2647
2648 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
2649 {
2650
2651         struct wpa_dbus_object_desc *obj_desc = NULL;
2652         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
2653         int next;
2654
2655         /* Do nothing if the control interface is not turned on */
2656         if (ctrl_iface == NULL)
2657                 return 0;
2658
2659         /* Create and set the interface's object path */
2660         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2661         if (wpa_s->dbus_new_path == NULL)
2662                 return -1;
2663         next = ctrl_iface->next_objid++;
2664         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
2665                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
2666                     next);
2667
2668         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2669         if (!obj_desc) {
2670                 wpa_printf(MSG_ERROR, "Not enough memory "
2671                            "to create object description");
2672                 goto err;
2673         }
2674
2675         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
2676                            wpas_dbus_interface_properties,
2677                            wpas_dbus_interface_signals);
2678
2679         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
2680                    wpa_s->dbus_new_path);
2681         if (wpa_dbus_register_object_per_iface(ctrl_iface,
2682                                                wpa_s->dbus_new_path,
2683                                                wpa_s->ifname, obj_desc))
2684                 goto err;
2685
2686         wpas_dbus_signal_interface_added(wpa_s);
2687
2688         return 0;
2689
2690 err:
2691         os_free(wpa_s->dbus_new_path);
2692         wpa_s->dbus_new_path = NULL;
2693         free_dbus_object_desc(obj_desc);
2694         return -1;
2695 }
2696
2697
2698 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
2699 {
2700         struct wpas_dbus_priv *ctrl_iface;
2701
2702         /* Do nothing if the control interface is not turned on */
2703         if (wpa_s == NULL || wpa_s->global == NULL)
2704                 return 0;
2705         ctrl_iface = wpa_s->global->dbus;
2706         if (ctrl_iface == NULL)
2707                 return 0;
2708
2709         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
2710                    wpa_s->dbus_new_path);
2711         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
2712                                                  wpa_s->dbus_new_path))
2713                 return -1;
2714
2715         wpas_dbus_signal_interface_removed(wpa_s);
2716
2717         os_free(wpa_s->dbus_new_path);
2718         wpa_s->dbus_new_path = NULL;
2719
2720         return 0;
2721 }
2722
2723 #ifdef CONFIG_P2P
2724
2725 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
2726         { "Properties", WPAS_DBUS_NEW_IFACE_P2P_PEER, "a{sv}",
2727           (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peer_properties,
2728           NULL, R
2729         },
2730         { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
2731           (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peer_ies,
2732           NULL, R
2733         },
2734         { NULL, NULL, NULL, NULL, NULL, 0 }
2735 };
2736
2737 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
2738
2739         { NULL, NULL, { END_ARGS } }
2740 };
2741
2742 /**
2743  * wpas_dbus_signal_peer - Send a peer related event signal
2744  * @wpa_s: %wpa_supplicant network interface data
2745  * @dev: peer device object
2746  * @interface: name of the interface emitting this signal.
2747  *      In case of peer objects, it would be emitted by either
2748  *      the "interface object" or by "peer objects"
2749  * @sig_name: signal name - DeviceFound
2750  *
2751  * Notify listeners about event related with newly found p2p peer device
2752  */
2753 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
2754                                   const u8 *dev_addr, const char *interface,
2755                                   const char *sig_name)
2756 {
2757         struct wpas_dbus_priv *iface;
2758         DBusMessage *msg;
2759         DBusMessageIter iter;
2760         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2761
2762         iface = wpa_s->global->dbus;
2763
2764         /* Do nothing if the control interface is not turned on */
2765         if (iface == NULL)
2766                 return;
2767
2768         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2769                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2770                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
2771
2772         msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
2773                                       sig_name);
2774         if (msg == NULL)
2775                 return;
2776
2777         dbus_message_iter_init_append(msg, &iter);
2778         path = peer_obj_path;
2779         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2780                                             &path))
2781                 goto err;
2782
2783         dbus_connection_send(iface->con, msg, NULL);
2784
2785         dbus_message_unref(msg);
2786         return;
2787
2788 err:
2789         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2790         dbus_message_unref(msg);
2791 }
2792
2793
2794 /**
2795  * wpas_dbus_signal_peer_found - Send a peer found signal
2796  * @wpa_s: %wpa_supplicant network interface data
2797  * @dev: peer device object
2798  *
2799  * Notify listeners about find a p2p peer device found
2800  */
2801 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
2802                                         const u8 *dev_addr)
2803 {
2804         wpas_dbus_signal_peer(wpa_s, dev_addr,
2805                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2806                               "DeviceFound");
2807 }
2808
2809 /**
2810  * wpas_dbus_signal_peer_lost - Send a peer lost signal
2811  * @wpa_s: %wpa_supplicant network interface data
2812  * @dev: peer device object
2813  *
2814  * Notify listeners about lost a p2p peer device
2815  */
2816 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
2817                                        const u8 *dev_addr)
2818 {
2819         wpas_dbus_signal_peer(wpa_s, dev_addr,
2820                               WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2821                               "DeviceLost");
2822 }
2823
2824 /**
2825  * wpas_dbus_register_peer - Register a discovered peer object with dbus
2826  * @wpa_s: wpa_supplicant interface structure
2827  * @ssid: network configuration data
2828  * Returns: 0 on success, -1 on failure
2829  *
2830  * Registers network representing object with dbus
2831  */
2832 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
2833 {
2834         struct wpas_dbus_priv *ctrl_iface;
2835         struct wpa_dbus_object_desc *obj_desc;
2836         struct peer_handler_args *arg;
2837         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2838
2839         /* Do nothing if the control interface is not turned on */
2840         if (wpa_s == NULL || wpa_s->global == NULL)
2841                 return 0;
2842
2843         ctrl_iface = wpa_s->global->dbus;
2844         if (ctrl_iface == NULL)
2845                 return 0;
2846
2847         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2848                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2849                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
2850
2851         wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
2852                    peer_obj_path);
2853         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2854         if (!obj_desc) {
2855                 wpa_printf(MSG_ERROR, "Not enough memory "
2856                            "to create object description");
2857                 goto err;
2858         }
2859
2860         /* allocate memory for handlers arguments */
2861         arg = os_zalloc(sizeof(struct peer_handler_args));
2862         if (!arg) {
2863                 wpa_printf(MSG_ERROR, "Not enough memory "
2864                            "to create arguments for method");
2865                 goto err;
2866         }
2867
2868         arg->wpa_s = wpa_s;
2869         os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
2870
2871         wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
2872                            NULL,
2873                            wpas_dbus_p2p_peer_properties,
2874                            wpas_dbus_p2p_peer_signals);
2875
2876         if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
2877                                                wpa_s->ifname, obj_desc))
2878                 goto err;
2879
2880         return 0;
2881
2882 err:
2883         free_dbus_object_desc(obj_desc);
2884         return -1;
2885 }
2886
2887 /**
2888  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
2889  * @wpa_s: wpa_supplicant interface structure
2890  * @dev_addr: p2p device addr
2891  * Returns: 0 on success, -1 on failure
2892  *
2893  * Registers network representing object with dbus
2894  */
2895 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
2896                                   const u8 *dev_addr)
2897 {
2898         struct wpas_dbus_priv *ctrl_iface;
2899         char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2900         int ret;
2901
2902         /* Do nothing if the control interface is not turned on */
2903         if (wpa_s == NULL || wpa_s->global == NULL ||
2904             wpa_s->dbus_new_path == NULL)
2905                 return 0;
2906         ctrl_iface = wpa_s->global->dbus;
2907         if (ctrl_iface == NULL)
2908                 return 0;
2909
2910         os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2911                     "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2912                     wpa_s->dbus_new_path, MAC2STR(dev_addr));
2913
2914         wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
2915                    peer_obj_path);
2916         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
2917
2918         return ret;
2919 }
2920
2921
2922 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
2923         { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
2924           (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_members,
2925           NULL, R
2926         },
2927         { "Properties",
2928           WPAS_DBUS_NEW_IFACE_P2P_GROUP, "a{sv}",
2929           (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_properties,
2930           (WPADBusPropertyAccessor) wpas_dbus_setter_p2p_group_properties,
2931           RW
2932         },
2933         { NULL, NULL, NULL, NULL, NULL, 0 }
2934 };
2935
2936 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
2937         { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
2938           {
2939                   { "peer", "o", ARG_OUT },
2940                   END_ARGS
2941           }
2942         },
2943         { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
2944           {
2945                   { "peer", "o", ARG_OUT },
2946                   END_ARGS
2947           }
2948         },
2949         { NULL, NULL, { END_ARGS } }
2950 };
2951
2952 /**
2953  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
2954  * @wpa_s: wpa_supplicant interface structure
2955  * @ssid: SSID struct
2956  * Returns: 0 on success, -1 on failure
2957  *
2958  * Registers p2p group representing object with dbus
2959  */
2960 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
2961                                   struct wpa_ssid *ssid)
2962 {
2963         struct wpas_dbus_priv *ctrl_iface;
2964         struct wpa_dbus_object_desc *obj_desc;
2965         char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2966
2967         /* Do nothing if the control interface is not turned on */
2968         if (wpa_s == NULL || wpa_s->global == NULL)
2969                 return;
2970
2971         ctrl_iface = wpa_s->global->dbus;
2972         if (ctrl_iface == NULL)
2973                 return;
2974
2975         if (wpa_s->dbus_groupobj_path) {
2976                 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
2977                            __func__, wpa_s->dbus_groupobj_path);
2978                 return;
2979         }
2980
2981         if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
2982                 return;
2983
2984         wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
2985         if (wpa_s->dbus_groupobj_path == NULL)
2986                 return;
2987
2988         wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
2989                    group_obj_path);
2990         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2991         if (!obj_desc) {
2992                 wpa_printf(MSG_ERROR, "Not enough memory "
2993                            "to create object description");
2994                 goto err;
2995         }
2996
2997         wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
2998                            wpas_dbus_p2p_group_properties,
2999                            wpas_dbus_p2p_group_signals);
3000
3001         if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3002                                                wpa_s->ifname, obj_desc))
3003                 goto err;
3004
3005         return;
3006
3007 err:
3008         if (wpa_s->dbus_groupobj_path) {
3009                 os_free(wpa_s->dbus_groupobj_path);
3010                 wpa_s->dbus_groupobj_path = NULL;
3011         }
3012
3013         free_dbus_object_desc(obj_desc);
3014 }
3015
3016 /**
3017  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3018  * @wpa_s: wpa_supplicant interface structure
3019  * @ssid: network name of the p2p group started
3020  */
3021 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3022                                     const struct wpa_ssid *ssid)
3023 {
3024         struct wpas_dbus_priv *ctrl_iface;
3025
3026         /* Do nothing if the control interface is not turned on */
3027         if (wpa_s == NULL || wpa_s->global == NULL)
3028                 return;
3029
3030         ctrl_iface = wpa_s->global->dbus;
3031         if (ctrl_iface == NULL)
3032                 return;
3033
3034         if (!wpa_s->dbus_groupobj_path) {
3035                 wpa_printf(MSG_DEBUG,
3036                            "%s: Group object '%s' already unregistered",
3037                            __func__, wpa_s->dbus_groupobj_path);
3038                 return;
3039         }
3040
3041         wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3042                    wpa_s->dbus_groupobj_path);
3043
3044         wpa_dbus_unregister_object_per_iface(ctrl_iface,
3045                                              wpa_s->dbus_groupobj_path);
3046
3047         os_free(wpa_s->dbus_groupobj_path);
3048         wpa_s->dbus_groupobj_path = NULL;
3049 }
3050
3051 static const struct wpa_dbus_property_desc
3052 wpas_dbus_p2p_groupmember_properties[] = {
3053         { "Properties", WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER, "a{sv}",
3054           (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_properties,
3055           NULL, R
3056         },
3057         { NULL, NULL, NULL, NULL, NULL, 0 }
3058 };
3059
3060 /**
3061  * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
3062  * object with dbus
3063  * @wpa_s: wpa_supplicant interface structure
3064  * @p2p_if_addr: i/f addr of the device joining this group
3065  *
3066  * Registers p2p groupmember representing object with dbus
3067  */
3068 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
3069                                         const u8 *p2p_if_addr)
3070 {
3071         struct wpas_dbus_priv *ctrl_iface;
3072         struct wpa_dbus_object_desc *obj_desc = NULL;
3073         struct groupmember_handler_args *arg;
3074         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3075
3076         /* Do nothing if the control interface is not turned on */
3077         if (wpa_s == NULL || wpa_s->global == NULL)
3078                 return;
3079
3080         ctrl_iface = wpa_s->global->dbus;
3081         if (ctrl_iface == NULL)
3082                 return;
3083
3084         if (!wpa_s->dbus_groupobj_path)
3085                 return;
3086
3087         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3088                 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3089                 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3090
3091         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3092         if (!obj_desc) {
3093                 wpa_printf(MSG_ERROR, "Not enough memory "
3094                            "to create object description");
3095                 goto err;
3096         }
3097
3098         /* allocate memory for handlers arguments */
3099         arg = os_zalloc(sizeof(struct groupmember_handler_args));
3100         if (!arg) {
3101                 wpa_printf(MSG_ERROR, "Not enough memory "
3102                            "to create arguments for method");
3103                 goto err;
3104         }
3105
3106         arg->wpa_s = wpa_s;
3107         os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
3108
3109         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3110                            wpas_dbus_p2p_groupmember_properties, NULL);
3111
3112         if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
3113                                                wpa_s->ifname, obj_desc))
3114                 goto err;
3115
3116         wpa_printf(MSG_INFO,
3117                    "dbus: Registered group member object '%s' successfully",
3118                    groupmember_obj_path);
3119         return;
3120
3121 err:
3122         free_dbus_object_desc(obj_desc);
3123 }
3124
3125 /**
3126  * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
3127  * object with dbus
3128  * @wpa_s: wpa_supplicant interface structure
3129  * @p2p_if_addr: i/f addr of the device joining this group
3130  *
3131  * Unregisters p2p groupmember representing object with dbus
3132  */
3133 void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
3134                                           const u8 *p2p_if_addr)
3135 {
3136         struct wpas_dbus_priv *ctrl_iface;
3137         char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3138
3139         /* Do nothing if the control interface is not turned on */
3140         if (wpa_s == NULL || wpa_s->global == NULL)
3141                 return;
3142
3143         ctrl_iface = wpa_s->global->dbus;
3144         if (ctrl_iface == NULL)
3145                 return;
3146
3147         if (!wpa_s->dbus_groupobj_path)
3148                 return;
3149
3150         os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3151                 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3152                 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3153
3154         wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
3155 }
3156
3157
3158 static const struct wpa_dbus_property_desc
3159         wpas_dbus_persistent_group_properties[] = {
3160         { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3161           (WPADBusPropertyAccessor)
3162           wpas_dbus_getter_persistent_group_properties,
3163           (WPADBusPropertyAccessor)
3164           wpas_dbus_setter_persistent_group_properties,
3165           RW
3166         },
3167         { NULL, NULL, NULL, NULL, NULL, 0 }
3168 };
3169
3170 /* No signals intended for persistent group objects */
3171
3172 /**
3173  * wpas_dbus_register_persistent_group - Register a configured(saved)
3174  *      persistent group with dbus
3175  * @wpa_s: wpa_supplicant interface structure
3176  * @ssid: persistent group (still represented as a network within wpa)
3177  *        configuration data
3178  * Returns: 0 on success, -1 on failure
3179  *
3180  * Registers a persistent group representing object with dbus.
3181  */
3182 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3183                                         struct wpa_ssid *ssid)
3184 {
3185         struct wpas_dbus_priv *ctrl_iface;
3186         struct wpa_dbus_object_desc *obj_desc;
3187         struct network_handler_args *arg;
3188         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3189
3190         /* Do nothing if the control interface is not turned on */
3191         if (wpa_s == NULL || wpa_s->global == NULL)
3192                 return 0;
3193
3194         /* Make sure ssid is a persistent group */
3195         if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3196                 return -1; /* should we return w/o complaining? */
3197
3198         ctrl_iface = wpa_s->global->dbus;
3199         if (ctrl_iface == NULL)
3200                 return 0;
3201
3202         /*
3203          * Intentionally not coming up with different numbering scheme
3204          * for persistent groups.
3205          */
3206         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3207                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3208                     wpa_s->dbus_new_path, ssid->id);
3209
3210         wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3211                    pgrp_obj_path);
3212         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3213         if (!obj_desc) {
3214                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3215                            "object description");
3216                 goto err;
3217         }
3218
3219         /*
3220          * Reusing the same context structure as that for networks
3221          * since these are represented using same data structure.
3222          */
3223         /* allocate memory for handlers arguments */
3224         arg = os_zalloc(sizeof(struct network_handler_args));
3225         if (!arg) {
3226                 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3227                            "arguments for method");
3228                 goto err;
3229         }
3230
3231         arg->wpa_s = wpa_s;
3232         arg->ssid = ssid;
3233
3234         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3235                            wpas_dbus_persistent_group_properties,
3236                            NULL);
3237
3238         if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3239                                                wpa_s->ifname, obj_desc))
3240                 goto err;
3241
3242         wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3243
3244         return 0;
3245
3246 err:
3247         free_dbus_object_desc(obj_desc);
3248         return -1;
3249 }
3250
3251
3252 /**
3253  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3254  *      from dbus
3255  * @wpa_s: wpa_supplicant interface structure
3256  * @nid: network id
3257  * Returns: 0 on success, -1 on failure
3258  *
3259  * Unregisters persistent group representing object from dbus
3260  *
3261  * NOTE: There is a slight issue with the semantics here. While the
3262  * implementation simply means the persistent group is unloaded from memory,
3263  * it should not get interpreted as the group is actually being erased/removed
3264  * from persistent storage as well.
3265  */
3266 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3267                                           int nid)
3268 {
3269         struct wpas_dbus_priv *ctrl_iface;
3270         char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3271         int ret;
3272
3273         /* Do nothing if the control interface is not turned on */
3274         if (wpa_s == NULL || wpa_s->global == NULL ||
3275             wpa_s->dbus_new_path == NULL)
3276                 return 0;
3277         ctrl_iface = wpa_s->global->dbus;
3278         if (ctrl_iface == NULL)
3279                 return 0;
3280
3281         os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3282                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3283                     wpa_s->dbus_new_path, nid);
3284
3285         wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3286                    pgrp_obj_path);
3287         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3288
3289         if (!ret)
3290                 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3291
3292         return ret;
3293 }
3294
3295 #endif /* CONFIG_P2P */