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