dbus: Change BSS property MaxRate to Rates
[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, 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 "wps/wps.h"
21 #include "../config.h"
22 #include "../wpa_supplicant_i.h"
23 #include "../bss.h"
24 #include "dbus_new_helpers.h"
25 #include "dbus_dict_helpers.h"
26 #include "dbus_new.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_common.h"
29 #include "dbus_common_i.h"
30
31
32 /**
33  * wpas_dbus_signal_interface - Send a interface related event signal
34  * @wpa_s: %wpa_supplicant network interface data
35  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
36  * @properties: Whether to add second argument with object properties
37  *
38  * Notify listeners about event related with interface
39  */
40 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
41                                        const char *sig_name, int properties)
42 {
43         struct wpas_dbus_priv *iface;
44         DBusMessage *msg;
45         DBusMessageIter iter, iter_dict;
46
47         iface = wpa_s->global->dbus;
48
49         /* Do nothing if the control interface is not turned on */
50         if (iface == NULL)
51                 return;
52
53         msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
54                                       WPAS_DBUS_NEW_INTERFACE, sig_name);
55         if (msg == NULL)
56                 return;
57
58         dbus_message_iter_init_append(msg, &iter);
59         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
60                                             &wpa_s->dbus_new_path))
61                 goto err;
62
63         if (properties) {
64                 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
65                         goto err;
66
67                 wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path,
68                                                WPAS_DBUS_NEW_IFACE_INTERFACE,
69                                                &iter_dict);
70
71                 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
72                         goto err;
73         }
74
75         dbus_connection_send(iface->con, msg, NULL);
76         dbus_message_unref(msg);
77         return;
78
79 err:
80         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
81         dbus_message_unref(msg);
82 }
83
84
85 /**
86  * wpas_dbus_signal_interface_added - Send a interface created signal
87  * @wpa_s: %wpa_supplicant network interface data
88  *
89  * Notify listeners about creating new interface
90  */
91 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
92 {
93         wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
94 }
95
96
97 /**
98  * wpas_dbus_signal_interface_removed - Send a interface removed signal
99  * @wpa_s: %wpa_supplicant network interface data
100  *
101  * Notify listeners about removing interface
102  */
103 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
104 {
105         wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
106
107 }
108
109
110 /**
111  * wpas_dbus_signal_scan_done - send scan done signal
112  * @wpa_s: %wpa_supplicant network interface data
113  * @success: indicates if scanning succeed or failed
114  *
115  * Notify listeners about finishing a scan
116  */
117 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
118 {
119         struct wpas_dbus_priv *iface;
120         DBusMessage *msg;
121         dbus_bool_t succ;
122
123         iface = wpa_s->global->dbus;
124
125         /* Do nothing if the control interface is not turned on */
126         if (iface == NULL)
127                 return;
128
129         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
130                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
131                                       "ScanDone");
132         if (msg == NULL)
133                 return;
134
135         succ = success ? TRUE : FALSE;
136         if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
137                                      DBUS_TYPE_INVALID))
138                 dbus_connection_send(iface->con, msg, NULL);
139         else
140                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
141         dbus_message_unref(msg);
142 }
143
144
145 /**
146  * wpas_dbus_signal_blob - Send a BSS related event signal
147  * @wpa_s: %wpa_supplicant network interface data
148  * @bss_obj_path: BSS object path
149  * @sig_name: signal name - BSSAdded or BSSRemoved
150  * @properties: Whether to add second argument with object properties
151  *
152  * Notify listeners about event related with BSS
153  */
154 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
155                                  const char *bss_obj_path,
156                                  const char *sig_name, int properties)
157 {
158         struct wpas_dbus_priv *iface;
159         DBusMessage *msg;
160         DBusMessageIter iter, iter_dict;
161
162         iface = wpa_s->global->dbus;
163
164         /* Do nothing if the control interface is not turned on */
165         if (iface == NULL)
166                 return;
167
168         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
169                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
170                                       sig_name);
171         if (msg == NULL)
172                 return;
173
174         dbus_message_iter_init_append(msg, &iter);
175         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
176                                             &bss_obj_path))
177                 goto err;
178
179         if (properties) {
180                 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
181                         goto err;
182
183                 wpa_dbus_get_object_properties(iface, bss_obj_path,
184                                                WPAS_DBUS_NEW_IFACE_BSSID,
185                                                &iter_dict);
186
187                 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
188                         goto err;
189         }
190
191         dbus_connection_send(iface->con, msg, NULL);
192         dbus_message_unref(msg);
193         return;
194
195 err:
196         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
197         dbus_message_unref(msg);
198 }
199
200
201 /**
202  * wpas_dbus_signal_bss_added - Send a BSS added signal
203  * @wpa_s: %wpa_supplicant network interface data
204  * @bss_obj_path: new BSS object path
205  *
206  * Notify listeners about adding new BSS
207  */
208 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
209                                        const char *bss_obj_path)
210 {
211         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
212 }
213
214
215 /**
216  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
217  * @wpa_s: %wpa_supplicant network interface data
218  * @bss_obj_path: BSS object path
219  *
220  * Notify listeners about removing BSS
221  */
222 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
223                                          const char *bss_obj_path)
224 {
225         wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
226 }
227
228
229 /**
230  * wpas_dbus_signal_blob - Send a blob related event signal
231  * @wpa_s: %wpa_supplicant network interface data
232  * @name: blob name
233  * @sig_name: signal name - BlobAdded or BlobRemoved
234  *
235  * Notify listeners about event related with blob
236  */
237 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
238                                   const char *name, const char *sig_name)
239 {
240         struct wpas_dbus_priv *iface;
241         DBusMessage *msg;
242
243         iface = wpa_s->global->dbus;
244
245         /* Do nothing if the control interface is not turned on */
246         if (iface == NULL)
247                 return;
248
249         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
250                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
251                                       sig_name);
252         if (msg == NULL)
253                 return;
254
255         if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
256                                      DBUS_TYPE_INVALID))
257                 dbus_connection_send(iface->con, msg, NULL);
258         else
259                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
260         dbus_message_unref(msg);
261 }
262
263
264 /**
265  * wpas_dbus_signal_blob_added - Send a blob added signal
266  * @wpa_s: %wpa_supplicant network interface data
267  * @name: blob name
268  *
269  * Notify listeners about adding a new blob
270  */
271 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
272                                  const char *name)
273 {
274         wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
275 }
276
277
278 /**
279  * wpas_dbus_signal_blob_removed - Send a blob removed signal
280  * @wpa_s: %wpa_supplicant network interface data
281  * @name: blob name
282  *
283  * Notify listeners about removing blob
284  */
285 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
286                                    const char *name)
287 {
288         wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
289 }
290
291
292 /**
293  * wpas_dbus_signal_network - Send a network related event signal
294  * @wpa_s: %wpa_supplicant network interface data
295  * @id: new network id
296  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
297  * @properties: determines if add second argument with object properties
298  *
299  * Notify listeners about event related with configured network
300  */
301 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
302                                      int id, const char *sig_name,
303                                      int properties)
304 {
305         struct wpas_dbus_priv *iface;
306         DBusMessage *msg;
307         DBusMessageIter iter, iter_dict;
308         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
309
310         iface = wpa_s->global->dbus;
311
312         /* Do nothing if the control interface is not turned on */
313         if (iface == NULL)
314                 return;
315
316         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
317                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
318                     wpa_s->dbus_new_path, id);
319
320         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
321                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
322                                       sig_name);
323         if (msg == NULL)
324                 return;
325
326         dbus_message_iter_init_append(msg, &iter);
327         path = net_obj_path;
328         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
329                                             &path))
330                 goto err;
331
332         if (properties) {
333                 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
334                         goto err;
335
336                 wpa_dbus_get_object_properties(iface, net_obj_path,
337                                                WPAS_DBUS_NEW_IFACE_NETWORK,
338                                                &iter_dict);
339
340                 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
341                         goto err;
342         }
343
344         dbus_connection_send(iface->con, msg, NULL);
345
346         dbus_message_unref(msg);
347         return;
348
349 err:
350         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
351         dbus_message_unref(msg);
352 }
353
354
355 /**
356  * wpas_dbus_signal_network_added - Send a network added signal
357  * @wpa_s: %wpa_supplicant network interface data
358  * @id: new network id
359  *
360  * Notify listeners about adding new network
361  */
362 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
363                                            int id)
364 {
365         wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
366 }
367
368
369 /**
370  * wpas_dbus_signal_network_removed - Send a network removed signal
371  * @wpa_s: %wpa_supplicant network interface data
372  * @id: network id
373  *
374  * Notify listeners about removing a network
375  */
376 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
377                                              int id)
378 {
379         wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
380 }
381
382
383 /**
384  * wpas_dbus_signal_network_selected - Send a network selected signal
385  * @wpa_s: %wpa_supplicant network interface data
386  * @id: network id
387  *
388  * Notify listeners about selecting a network
389  */
390 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
391 {
392         wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
393 }
394
395
396 /**
397  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
398  * @wpa_s: %wpa_supplicant network interface data
399  * @ssid: configured network which Enabled property has changed
400  *
401  * Sends PropertyChanged signals containing new value of Enabled property
402  * for specified network
403  */
404 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
405                                               struct wpa_ssid *ssid)
406 {
407
408         struct network_handler_args args = { wpa_s, ssid };
409         char path[WPAS_DBUS_OBJECT_PATH_MAX];
410         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
411                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
412                     wpa_s->dbus_new_path, ssid->id);
413
414         wpa_dbus_signal_property_changed(wpa_s->global->dbus,
415                                          (WPADBusPropertyAccessor)
416                                          wpas_dbus_getter_enabled, &args,
417                                          path, WPAS_DBUS_NEW_IFACE_NETWORK,
418                                          "Enabled");
419 }
420
421
422 #ifdef CONFIG_WPS
423
424 /**
425  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
426  * @wpa_s: %wpa_supplicant network interface data
427  *
428  * Sends Event dbus signal with name "success" and empty dict as arguments
429  */
430 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
431 {
432
433         DBusMessage *msg;
434         DBusMessageIter iter, dict_iter;
435         struct wpas_dbus_priv *iface;
436         char *key = "success";
437
438         iface = wpa_s->global->dbus;
439
440         /* Do nothing if the control interface is not turned on */
441         if (iface == NULL)
442                 return;
443
444         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
445                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
446         if (msg == NULL)
447                 return;
448
449         dbus_message_iter_init_append(msg, &iter);
450
451         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
452             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
453             !wpa_dbus_dict_close_write(&iter, &dict_iter))
454                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
455         else
456                 dbus_connection_send(iface->con, msg, NULL);
457
458         dbus_message_unref(msg);
459 }
460
461
462 /**
463  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
464  * @wpa_s: %wpa_supplicant network interface data
465  *
466  * Sends Event dbus signal with name "fail" and dictionary containing
467  * "msg field with fail message number (int32) as arguments
468  */
469 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
470                                      struct wps_event_fail *fail)
471 {
472
473         DBusMessage *msg;
474         DBusMessageIter iter, dict_iter;
475         struct wpas_dbus_priv *iface;
476         char *key = "fail";
477
478         iface = wpa_s->global->dbus;
479
480         /* Do nothing if the control interface is not turned on */
481         if (iface == NULL)
482                 return;
483
484         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
485                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
486         if (msg == NULL)
487                 return;
488
489         dbus_message_iter_init_append(msg, &iter);
490
491         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
492             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
493             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
494             !wpa_dbus_dict_close_write(&iter, &dict_iter))
495                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
496         else
497                 dbus_connection_send(iface->con, msg, NULL);
498
499         dbus_message_unref(msg);
500 }
501
502
503 /**
504  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
505  * @wpa_s: %wpa_supplicant network interface data
506  *
507  * Sends Event dbus signal with name "m2d" and dictionary containing
508  * fields of wps_event_m2d structure.
509  */
510 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
511                                     struct wps_event_m2d *m2d)
512 {
513
514         DBusMessage *msg;
515         DBusMessageIter iter, dict_iter;
516         struct wpas_dbus_priv *iface;
517         char *key = "m2d";
518
519         iface = wpa_s->global->dbus;
520
521         /* Do nothing if the control interface is not turned on */
522         if (iface == NULL)
523                 return;
524
525         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
526                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
527         if (msg == NULL)
528                 return;
529
530         dbus_message_iter_init_append(msg, &iter);
531
532         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
533             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
534             !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
535                                          m2d->config_methods) ||
536             !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
537                                              (const char *) m2d->manufacturer,
538                                              m2d->manufacturer_len) ||
539             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
540                                              (const char *) m2d->model_name,
541                                              m2d->model_name_len) ||
542             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
543                                              (const char *) m2d->model_number,
544                                              m2d->model_number_len) ||
545             !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
546                                              (const char *)
547                                              m2d->serial_number,
548                                              m2d->serial_number_len) ||
549             !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
550                                              (const char *) m2d->dev_name,
551                                              m2d->dev_name_len) ||
552             !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
553                                              (const char *)
554                                              m2d->primary_dev_type, 8) ||
555             !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
556                                          m2d->config_error) ||
557             !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
558                                          m2d->dev_password_id) ||
559             !wpa_dbus_dict_close_write(&iter, &dict_iter))
560                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
561         else
562                 dbus_connection_send(iface->con, msg, NULL);
563
564         dbus_message_unref(msg);
565 }
566
567
568 /**
569  * wpas_dbus_signal_wps_cred - Signals new credentials
570  * @wpa_s: %wpa_supplicant network interface data
571  *
572  * Sends signal with credentials in directory argument
573  */
574 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
575                                const struct wps_credential *cred)
576 {
577         DBusMessage *msg;
578         DBusMessageIter iter, dict_iter;
579         struct wpas_dbus_priv *iface;
580         char *auth_type[6]; /* we have six possible authorization types */
581         int at_num = 0;
582         char *encr_type[4]; /* we have four possible encryption types */
583         int et_num = 0;
584
585         iface = wpa_s->global->dbus;
586
587         /* Do nothing if the control interface is not turned on */
588         if (iface == NULL)
589                 return;
590
591         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
592                                       WPAS_DBUS_NEW_IFACE_WPS,
593                                       "Credentials");
594         if (msg == NULL)
595                 return;
596
597         dbus_message_iter_init_append(msg, &iter);
598         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
599                 goto nomem;
600
601         if (cred->auth_type & WPS_AUTH_OPEN)
602                 auth_type[at_num++] = "open";
603         if (cred->auth_type & WPS_AUTH_WPAPSK)
604                 auth_type[at_num++] = "wpa-psk";
605         if (cred->auth_type & WPS_AUTH_SHARED)
606                 auth_type[at_num++] = "shared";
607         if (cred->auth_type & WPS_AUTH_WPA)
608                 auth_type[at_num++] = "wpa-eap";
609         if (cred->auth_type & WPS_AUTH_WPA2)
610                 auth_type[at_num++] = "wpa2-eap";
611         if (cred->auth_type & WPS_AUTH_WPA2PSK)
612                 auth_type[at_num++] =
613                 "wpa2-psk";
614
615         if (cred->encr_type & WPS_ENCR_NONE)
616                 encr_type[et_num++] = "none";
617         if (cred->encr_type & WPS_ENCR_WEP)
618                 encr_type[et_num++] = "wep";
619         if (cred->encr_type & WPS_ENCR_TKIP)
620                 encr_type[et_num++] = "tkip";
621         if (cred->encr_type & WPS_ENCR_AES)
622                 encr_type[et_num++] = "aes";
623
624         if (wpa_s->current_ssid) {
625                 if (!wpa_dbus_dict_append_byte_array(
626                             &dict_iter, "BSSID",
627                             (const char *) wpa_s->current_ssid->bssid,
628                             ETH_ALEN))
629                         goto nomem;
630         }
631
632         if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
633                                              (const char *) cred->ssid,
634                                              cred->ssid_len) ||
635             !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
636                                                (const char **) auth_type,
637                                                at_num) ||
638             !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
639                                                (const char **) encr_type,
640                                                et_num) ||
641             !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
642                                              (const char *) cred->key,
643                                              cred->key_len) ||
644             !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
645                                          cred->key_idx) ||
646             !wpa_dbus_dict_close_write(&iter, &dict_iter))
647                 goto nomem;
648
649         dbus_connection_send(iface->con, msg, NULL);
650
651 nomem:
652         dbus_message_unref(msg);
653 }
654
655 #endif /* CONFIG_WPS */
656
657
658 /**
659  * wpas_dbus_signal_prop_changed - Signals change of property
660  * @wpa_s: %wpa_supplicant network interface data
661  * @property: indicates which property has changed
662  *
663  * Sends ProertyChanged signals with path, interface and arguments
664  * depending on which property has changed.
665  */
666 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
667                                    enum wpas_dbus_prop property)
668 {
669         WPADBusPropertyAccessor getter;
670         char *prop;
671
672         switch (property) {
673         case WPAS_DBUS_PROP_AP_SCAN:
674                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
675                 prop = "ApScan";
676                 break;
677         case WPAS_DBUS_PROP_SCANNING:
678                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
679                 prop = "Scanning";
680                 break;
681         case WPAS_DBUS_PROP_STATE:
682                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
683                 prop = "State";
684                 break;
685         case WPAS_DBUS_PROP_CURRENT_BSS:
686                 getter = (WPADBusPropertyAccessor)
687                         wpas_dbus_getter_current_bss;
688                 prop = "CurrentBSS";
689                 break;
690         case WPAS_DBUS_PROP_CURRENT_NETWORK:
691                 getter = (WPADBusPropertyAccessor)
692                         wpas_dbus_getter_current_network;
693                 prop = "CurrentNetwork";
694                 break;
695         default:
696                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
697                            __func__, property);
698                 return;
699         }
700
701         wpa_dbus_signal_property_changed(wpa_s->global->dbus,
702                                          getter, wpa_s, wpa_s->dbus_new_path,
703                                          WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
704 }
705
706
707 /**
708  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
709  * @global: wpa_global structure
710  *
711  * Sends ProertyChanged signals informing that debug level has changed.
712  */
713 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
714 {
715         wpa_dbus_signal_property_changed(global->dbus,
716                                          (WPADBusPropertyAccessor)
717                                          wpas_dbus_getter_debug_level,
718                                          global, WPAS_DBUS_NEW_PATH,
719                                          WPAS_DBUS_NEW_INTERFACE,
720                                          "DebugLevel");
721 }
722
723
724 /**
725  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
726  * @global: wpa_global structure
727  *
728  * Sends ProertyChanged signals informing that debug timestamp has changed.
729  */
730 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
731 {
732         wpa_dbus_signal_property_changed(global->dbus,
733                                          (WPADBusPropertyAccessor)
734                                          wpas_dbus_getter_debug_timestamp,
735                                          global, WPAS_DBUS_NEW_PATH,
736                                          WPAS_DBUS_NEW_INTERFACE,
737                                          "DebugTimestamp");
738 }
739
740
741 /**
742  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
743  * @global: wpa_global structure
744  *
745  * Sends ProertyChanged signals informing that debug show_keys has changed.
746  */
747 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
748 {
749         wpa_dbus_signal_property_changed(global->dbus,
750                                          (WPADBusPropertyAccessor)
751                                          wpas_dbus_getter_debug_show_keys,
752                                          global, WPAS_DBUS_NEW_PATH,
753                                          WPAS_DBUS_NEW_INTERFACE,
754                                          "DebugShowKeys");
755 }
756
757
758 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
759                                void *priv,
760                                WPADBusArgumentFreeFunction priv_free,
761                                const struct wpa_dbus_method_desc *methods,
762                                const struct wpa_dbus_property_desc *properties,
763                                const struct wpa_dbus_signal_desc *signals)
764 {
765         obj_desc->user_data = priv;
766         obj_desc->user_data_free_func = priv_free;
767         obj_desc->methods = methods;
768         obj_desc->properties = properties;
769         obj_desc->signals = signals;
770 }
771
772
773 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
774         { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
775           (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
776           {
777                   { "args", "a{sv}", ARG_IN },
778                   { "path", "o", ARG_OUT },
779                   END_ARGS
780           }
781         },
782         { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
783           (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
784           {
785                   { "path", "o", ARG_IN },
786                   END_ARGS
787           }
788         },
789         { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
790           (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
791           {
792                   { "ifname", "s", ARG_IN },
793                   { "path", "o", ARG_OUT },
794                   END_ARGS
795           }
796         },
797         { NULL, NULL, NULL, { END_ARGS } }
798 };
799
800 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
801         { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
802           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
803           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
804           RW
805         },
806         { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
807           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
808           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
809           RW
810         },
811         { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
812           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
813           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
814           RW
815         },
816         { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
817           (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
818           NULL,
819           R
820         },
821         { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
822           (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
823           NULL,
824           R
825         },
826         { NULL, NULL, NULL, NULL, NULL, 0 }
827 };
828
829 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
830         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
831           {
832                   { "path", "o", ARG_OUT },
833                   { "properties", "a{sv}", ARG_OUT },
834                   END_ARGS
835           }
836         },
837         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
838           {
839                   { "path", "o", ARG_OUT },
840                   END_ARGS
841           }
842         },
843         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
844           {
845                   { "properties", "a{sv}", ARG_OUT },
846                   END_ARGS
847           }
848         },
849         { NULL, NULL, { END_ARGS } }
850 };
851
852
853 /**
854  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
855  * @global: Pointer to global data from wpa_supplicant_init()
856  * Returns: 0 on success or -1 on failure
857  *
858  * Initialize the dbus control interface for wpa_supplicantand and start
859  * receiving commands from external programs over the bus.
860  */
861 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
862 {
863         struct wpa_dbus_object_desc *obj_desc;
864         int ret;
865
866         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
867         if (!obj_desc) {
868                 wpa_printf(MSG_ERROR, "Not enough memory "
869                            "to create object description");
870                 return -1;
871         }
872
873         wpas_dbus_register(obj_desc, priv->global, NULL,
874                            wpas_dbus_global_methods,
875                            wpas_dbus_global_properties,
876                            wpas_dbus_global_signals);
877
878         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
879                    WPAS_DBUS_NEW_PATH);
880         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
881                                        WPAS_DBUS_NEW_SERVICE,
882                                        obj_desc);
883         if (ret < 0)
884                 free_dbus_object_desc(obj_desc);
885         else
886                 priv->dbus_new_initialized = 1;
887
888         return ret;
889 }
890
891
892 /**
893  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
894  * wpa_supplicant
895  * @iface: Pointer to dbus private data from wpas_dbus_init()
896  *
897  * Deinitialize the dbus control interface that was initialized with
898  * wpas_dbus_ctrl_iface_init().
899  */
900 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
901 {
902         if (!iface->dbus_new_initialized)
903                 return;
904         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
905                    WPAS_DBUS_NEW_PATH);
906         dbus_connection_unregister_object_path(iface->con,
907                                                WPAS_DBUS_NEW_PATH);
908 }
909
910
911 static void wpa_dbus_free(void *ptr)
912 {
913         os_free(ptr);
914 }
915
916
917 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
918         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
919           (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
920           (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
921           RW
922         },
923         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
924           (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
925           (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
926           RW
927         },
928         { NULL, NULL, NULL, NULL, NULL, 0 }
929 };
930
931
932 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
933         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
934           {
935                   { "properties", "a{sv}", ARG_OUT },
936                   END_ARGS
937           }
938         },
939         { NULL, NULL, { END_ARGS } }
940 };
941
942
943 /**
944  * wpas_dbus_register_network - Register a configured network with dbus
945  * @wpa_s: wpa_supplicant interface structure
946  * @ssid: network configuration data
947  * Returns: 0 on success, -1 on failure
948  *
949  * Registers network representing object with dbus
950  */
951 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
952                                struct wpa_ssid *ssid)
953 {
954         struct wpas_dbus_priv *ctrl_iface;
955         struct wpa_dbus_object_desc *obj_desc;
956         struct network_handler_args *arg;
957         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
958
959         /* Do nothing if the control interface is not turned on */
960         if (wpa_s == NULL || wpa_s->global == NULL)
961                 return 0;
962         ctrl_iface = wpa_s->global->dbus;
963         if (ctrl_iface == NULL)
964                 return 0;
965
966         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
967                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
968                     wpa_s->dbus_new_path, ssid->id);
969
970         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
971                    net_obj_path);
972         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
973         if (!obj_desc) {
974                 wpa_printf(MSG_ERROR, "Not enough memory "
975                            "to create object description");
976                 goto err;
977         }
978
979         /* allocate memory for handlers arguments */
980         arg = os_zalloc(sizeof(struct network_handler_args));
981         if (!arg) {
982                 wpa_printf(MSG_ERROR, "Not enough memory "
983                            "to create arguments for method");
984                 goto err;
985         }
986
987         arg->wpa_s = wpa_s;
988         arg->ssid = ssid;
989
990         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
991                            wpas_dbus_network_properties,
992                            wpas_dbus_network_signals);
993
994         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
995                                                wpa_s->ifname, obj_desc))
996                 goto err;
997
998         wpas_dbus_signal_network_added(wpa_s, ssid->id);
999
1000         return 0;
1001
1002 err:
1003         free_dbus_object_desc(obj_desc);
1004         return -1;
1005 }
1006
1007
1008 /**
1009  * wpas_dbus_unregister_network - Unregister a configured network from dbus
1010  * @wpa_s: wpa_supplicant interface structure
1011  * @nid: network id
1012  * Returns: 0 on success, -1 on failure
1013  *
1014  * Unregisters network representing object from dbus
1015  */
1016 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1017 {
1018         struct wpas_dbus_priv *ctrl_iface;
1019         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1020         int ret;
1021
1022         /* Do nothing if the control interface is not turned on */
1023         if (wpa_s == NULL || wpa_s->global == NULL)
1024                 return 0;
1025         ctrl_iface = wpa_s->global->dbus;
1026         if (ctrl_iface == NULL)
1027                 return 0;
1028
1029         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1030                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1031                     wpa_s->dbus_new_path, nid);
1032
1033         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1034                    net_obj_path);
1035         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1036
1037         if (!ret)
1038                 wpas_dbus_signal_network_removed(wpa_s, nid);
1039
1040         return ret;
1041 }
1042
1043
1044 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
1045         { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1046           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1047           NULL,
1048           R
1049         },
1050         { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1051           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1052           NULL,
1053           R
1054         },
1055         { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1056           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1057           NULL,
1058           R
1059         },
1060         { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1061           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1062           NULL,
1063           R
1064         },
1065         { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1066           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1067           NULL,
1068           R
1069         },
1070         { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1071           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1072           NULL,
1073           R
1074         },
1075         { "Rates", WPAS_DBUS_NEW_IFACE_BSSID, "au",
1076           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
1077           NULL,
1078           R
1079         },
1080         { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1081           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1082           NULL,
1083           R
1084         },
1085         { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1086           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1087           NULL,
1088           R
1089         },
1090         { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1091           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1092           NULL,
1093           R
1094         },
1095         { NULL, NULL, NULL, NULL, NULL, 0 }
1096 };
1097
1098
1099 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
1100         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1101           {
1102                   { "properties", "a{sv}", ARG_OUT },
1103                   END_ARGS
1104           }
1105         },
1106         { NULL, NULL, { END_ARGS } }
1107 };
1108
1109
1110 /**
1111  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1112  * @wpa_s: wpa_supplicant interface structure
1113  * @bssid: scanned network bssid
1114  * @id: unique BSS identifier
1115  * Returns: 0 on success, -1 on failure
1116  *
1117  * Unregisters BSS representing object from dbus
1118  */
1119 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1120                              u8 bssid[ETH_ALEN], unsigned int id)
1121 {
1122         struct wpas_dbus_priv *ctrl_iface;
1123         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1124
1125         /* Do nothing if the control interface is not turned on */
1126         if (wpa_s == NULL || wpa_s->global == NULL)
1127                 return 0;
1128         ctrl_iface = wpa_s->global->dbus;
1129         if (ctrl_iface == NULL)
1130                 return 0;
1131
1132         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1133                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1134                     wpa_s->dbus_new_path, id);
1135
1136         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1137                    bss_obj_path);
1138         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1139                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
1140                            bss_obj_path);
1141                 return -1;
1142         }
1143
1144         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1145
1146         return 0;
1147 }
1148
1149
1150 /**
1151  * wpas_dbus_register_bss - Register a scanned BSS with dbus
1152  * @wpa_s: wpa_supplicant interface structure
1153  * @bssid: scanned network bssid
1154  * @id: unique BSS identifier
1155  * Returns: 0 on success, -1 on failure
1156  *
1157  * Registers BSS representing object with dbus
1158  */
1159 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1160                            u8 bssid[ETH_ALEN], unsigned int id)
1161 {
1162         struct wpas_dbus_priv *ctrl_iface;
1163         struct wpa_dbus_object_desc *obj_desc;
1164         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1165         struct bss_handler_args *arg;
1166
1167         /* Do nothing if the control interface is not turned on */
1168         if (wpa_s == NULL || wpa_s->global == NULL)
1169                 return 0;
1170         ctrl_iface = wpa_s->global->dbus;
1171         if (ctrl_iface == NULL)
1172                 return 0;
1173
1174         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1175                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1176                     wpa_s->dbus_new_path, id);
1177
1178         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1179         if (!obj_desc) {
1180                 wpa_printf(MSG_ERROR, "Not enough memory "
1181                            "to create object description");
1182                 goto err;
1183         }
1184
1185         arg = os_zalloc(sizeof(struct bss_handler_args));
1186         if (!arg) {
1187                 wpa_printf(MSG_ERROR, "Not enough memory "
1188                            "to create arguments for handler");
1189                 goto err;
1190         }
1191         arg->wpa_s = wpa_s;
1192         arg->id = id;
1193
1194         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1195                            wpas_dbus_bss_properties,
1196                            wpas_dbus_bss_signals);
1197
1198         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1199                    bss_obj_path);
1200         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1201                                                wpa_s->ifname, obj_desc)) {
1202                 wpa_printf(MSG_ERROR,
1203                            "Cannot register BSSID dbus object %s.",
1204                            bss_obj_path);
1205                 goto err;
1206         }
1207
1208         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1209
1210         return 0;
1211
1212 err:
1213         free_dbus_object_desc(obj_desc);
1214         return -1;
1215 }
1216
1217
1218 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
1219         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1220           (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1221           {
1222                   { "args", "a{sv}", ARG_IN },
1223                   END_ARGS
1224           }
1225         },
1226         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1227           (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1228           {
1229                   END_ARGS
1230           }
1231         },
1232         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1233           (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1234           {
1235                   { "args", "a{sv}", ARG_IN },
1236                   { "path", "o", ARG_OUT },
1237                   END_ARGS
1238           }
1239         },
1240         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1241           (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1242           {
1243                   { "path", "o", ARG_IN },
1244                   END_ARGS
1245           }
1246         },
1247         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1248           (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1249           {
1250                   { "path", "o", ARG_IN },
1251                   END_ARGS
1252           }
1253         },
1254         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1255           (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1256           {
1257                   { "name", "s", ARG_IN },
1258                   { "data", "ay", ARG_IN },
1259                   END_ARGS
1260           }
1261         },
1262         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1263           (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1264           {
1265                   { "name", "s", ARG_IN },
1266                   { "data", "ay", ARG_OUT },
1267                   END_ARGS
1268           }
1269         },
1270         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1271           (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1272           {
1273                   { "name", "s", ARG_IN },
1274                   END_ARGS
1275           }
1276         },
1277 #ifdef CONFIG_WPS
1278         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1279           (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1280           {
1281                   { "args", "a{sv}", ARG_IN },
1282                   { "output", "a{sv}", ARG_OUT },
1283                   END_ARGS
1284           }
1285         },
1286 #endif /* CONFIG_WPS */
1287         { NULL, NULL, NULL, { END_ARGS } }
1288 };
1289
1290 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
1291         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1292           (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1293           NULL, R
1294         },
1295         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1296           (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1297           NULL, R
1298         },
1299         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1300           (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1301           NULL, R
1302         },
1303         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1304           (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1305           (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1306           RW
1307         },
1308         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1309           (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1310           NULL, R
1311         },
1312         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1313           (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1314           NULL, R
1315         },
1316         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1317           (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1318           NULL, R
1319         },
1320         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1321           (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1322           NULL, R
1323         },
1324         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1325           (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1326           NULL, R
1327         },
1328         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1329           (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1330           NULL, R
1331         },
1332         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1333           (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1334           NULL, R
1335         },
1336         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1337           (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1338           NULL, R
1339         },
1340 #ifdef CONFIG_WPS
1341         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1342           (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1343           (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1344           RW
1345         },
1346 #endif /* CONFIG_WPS */
1347         { NULL, NULL, NULL, NULL, NULL, 0 }
1348 };
1349
1350 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
1351         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1352           {
1353                   { "success", "b", ARG_OUT },
1354                   END_ARGS
1355           }
1356         },
1357         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1358           {
1359                   { "path", "o", ARG_OUT },
1360                   { "properties", "a{sv}", ARG_OUT },
1361                   END_ARGS
1362           }
1363         },
1364         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1365           {
1366                   { "path", "o", ARG_OUT },
1367                   END_ARGS
1368           }
1369         },
1370         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1371           {
1372                   { "name", "s", ARG_OUT },
1373                   END_ARGS
1374           }
1375         },
1376         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1377           {
1378                   { "name", "s", ARG_OUT },
1379                   END_ARGS
1380           }
1381         },
1382         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1383           {
1384                   { "path", "o", ARG_OUT },
1385                   { "properties", "a{sv}", ARG_OUT },
1386                   END_ARGS
1387           }
1388         },
1389         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1390           {
1391                   { "path", "o", ARG_OUT },
1392                   END_ARGS
1393           }
1394         },
1395         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1396           {
1397                   { "path", "o", ARG_OUT },
1398                   END_ARGS
1399           }
1400         },
1401         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1402           {
1403                   { "properties", "a{sv}", ARG_OUT },
1404                   END_ARGS
1405           }
1406         },
1407 #ifdef CONFIG_WPS
1408         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1409           {
1410                   { "name", "s", ARG_OUT },
1411                   { "args", "a{sv}", ARG_OUT },
1412                   END_ARGS
1413           }
1414         },
1415         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1416           {
1417                   { "credentials", "a{sv}", ARG_OUT },
1418                   END_ARGS
1419           }
1420         },
1421         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1422           {
1423                   { "properties", "a{sv}", ARG_OUT },
1424                   END_ARGS
1425           }
1426         },
1427 #endif /* CONFIG_WPS */
1428         { NULL, NULL, { END_ARGS } }
1429 };
1430
1431
1432 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1433 {
1434
1435         struct wpa_dbus_object_desc *obj_desc = NULL;
1436         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1437         int next;
1438
1439         /* Do nothing if the control interface is not turned on */
1440         if (ctrl_iface == NULL)
1441                 return 0;
1442
1443         /* Create and set the interface's object path */
1444         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1445         if (wpa_s->dbus_new_path == NULL)
1446                 return -1;
1447         next = ctrl_iface->next_objid++;
1448         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
1449                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1450                     next);
1451
1452         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1453         if (!obj_desc) {
1454                 wpa_printf(MSG_ERROR, "Not enough memory "
1455                            "to create object description");
1456                 goto err;
1457         }
1458
1459         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1460                            wpas_dbus_interface_properties,
1461                            wpas_dbus_interface_signals);
1462
1463         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
1464                    wpa_s->dbus_new_path);
1465         if (wpa_dbus_register_object_per_iface(ctrl_iface,
1466                                                wpa_s->dbus_new_path,
1467                                                wpa_s->ifname, obj_desc))
1468                 goto err;
1469
1470         wpas_dbus_signal_interface_added(wpa_s);
1471
1472         return 0;
1473
1474 err:
1475         os_free(wpa_s->dbus_new_path);
1476         wpa_s->dbus_new_path = NULL;
1477         free_dbus_object_desc(obj_desc);
1478         return -1;
1479 }
1480
1481
1482 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1483 {
1484         struct wpas_dbus_priv *ctrl_iface;
1485
1486         /* Do nothing if the control interface is not turned on */
1487         if (wpa_s == NULL || wpa_s->global == NULL)
1488                 return 0;
1489         ctrl_iface = wpa_s->global->dbus;
1490         if (ctrl_iface == NULL)
1491                 return 0;
1492
1493         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1494                    wpa_s->dbus_new_path);
1495         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1496                                                  wpa_s->dbus_new_path))
1497                 return -1;
1498
1499         wpas_dbus_signal_interface_removed(wpa_s);
1500
1501         os_free(wpa_s->dbus_new_path);
1502         wpa_s->dbus_new_path = NULL;
1503
1504         return 0;
1505 }