dbus: Fix crash on property change if D-Bus API is disabled
[libeap.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         char path[WPAS_DBUS_OBJECT_PATH_MAX];
409         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
410                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
411                     wpa_s->dbus_new_path, ssid->id);
412
413         wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
414                                        WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
415 }
416
417
418 #ifdef CONFIG_WPS
419
420 /**
421  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
422  * @wpa_s: %wpa_supplicant network interface data
423  *
424  * Sends Event dbus signal with name "success" and empty dict as arguments
425  */
426 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
427 {
428
429         DBusMessage *msg;
430         DBusMessageIter iter, dict_iter;
431         struct wpas_dbus_priv *iface;
432         char *key = "success";
433
434         iface = wpa_s->global->dbus;
435
436         /* Do nothing if the control interface is not turned on */
437         if (iface == NULL)
438                 return;
439
440         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
441                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
442         if (msg == NULL)
443                 return;
444
445         dbus_message_iter_init_append(msg, &iter);
446
447         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
448             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
449             !wpa_dbus_dict_close_write(&iter, &dict_iter))
450                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
451         else
452                 dbus_connection_send(iface->con, msg, NULL);
453
454         dbus_message_unref(msg);
455 }
456
457
458 /**
459  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
460  * @wpa_s: %wpa_supplicant network interface data
461  *
462  * Sends Event dbus signal with name "fail" and dictionary containing
463  * "msg field with fail message number (int32) as arguments
464  */
465 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
466                                      struct wps_event_fail *fail)
467 {
468
469         DBusMessage *msg;
470         DBusMessageIter iter, dict_iter;
471         struct wpas_dbus_priv *iface;
472         char *key = "fail";
473
474         iface = wpa_s->global->dbus;
475
476         /* Do nothing if the control interface is not turned on */
477         if (iface == NULL)
478                 return;
479
480         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
481                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
482         if (msg == NULL)
483                 return;
484
485         dbus_message_iter_init_append(msg, &iter);
486
487         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
488             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
489             !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
490             !wpa_dbus_dict_close_write(&iter, &dict_iter))
491                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
492         else
493                 dbus_connection_send(iface->con, msg, NULL);
494
495         dbus_message_unref(msg);
496 }
497
498
499 /**
500  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
501  * @wpa_s: %wpa_supplicant network interface data
502  *
503  * Sends Event dbus signal with name "m2d" and dictionary containing
504  * fields of wps_event_m2d structure.
505  */
506 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
507                                     struct wps_event_m2d *m2d)
508 {
509
510         DBusMessage *msg;
511         DBusMessageIter iter, dict_iter;
512         struct wpas_dbus_priv *iface;
513         char *key = "m2d";
514
515         iface = wpa_s->global->dbus;
516
517         /* Do nothing if the control interface is not turned on */
518         if (iface == NULL)
519                 return;
520
521         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
522                                       WPAS_DBUS_NEW_IFACE_WPS, "Event");
523         if (msg == NULL)
524                 return;
525
526         dbus_message_iter_init_append(msg, &iter);
527
528         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
529             !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
530             !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
531                                          m2d->config_methods) ||
532             !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
533                                              (const char *) m2d->manufacturer,
534                                              m2d->manufacturer_len) ||
535             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
536                                              (const char *) m2d->model_name,
537                                              m2d->model_name_len) ||
538             !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
539                                              (const char *) m2d->model_number,
540                                              m2d->model_number_len) ||
541             !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
542                                              (const char *)
543                                              m2d->serial_number,
544                                              m2d->serial_number_len) ||
545             !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
546                                              (const char *) m2d->dev_name,
547                                              m2d->dev_name_len) ||
548             !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
549                                              (const char *)
550                                              m2d->primary_dev_type, 8) ||
551             !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
552                                          m2d->config_error) ||
553             !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
554                                          m2d->dev_password_id) ||
555             !wpa_dbus_dict_close_write(&iter, &dict_iter))
556                 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
557         else
558                 dbus_connection_send(iface->con, msg, NULL);
559
560         dbus_message_unref(msg);
561 }
562
563
564 /**
565  * wpas_dbus_signal_wps_cred - Signals new credentials
566  * @wpa_s: %wpa_supplicant network interface data
567  *
568  * Sends signal with credentials in directory argument
569  */
570 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
571                                const struct wps_credential *cred)
572 {
573         DBusMessage *msg;
574         DBusMessageIter iter, dict_iter;
575         struct wpas_dbus_priv *iface;
576         char *auth_type[6]; /* we have six possible authorization types */
577         int at_num = 0;
578         char *encr_type[4]; /* we have four possible encryption types */
579         int et_num = 0;
580
581         iface = wpa_s->global->dbus;
582
583         /* Do nothing if the control interface is not turned on */
584         if (iface == NULL)
585                 return;
586
587         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588                                       WPAS_DBUS_NEW_IFACE_WPS,
589                                       "Credentials");
590         if (msg == NULL)
591                 return;
592
593         dbus_message_iter_init_append(msg, &iter);
594         if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
595                 goto nomem;
596
597         if (cred->auth_type & WPS_AUTH_OPEN)
598                 auth_type[at_num++] = "open";
599         if (cred->auth_type & WPS_AUTH_WPAPSK)
600                 auth_type[at_num++] = "wpa-psk";
601         if (cred->auth_type & WPS_AUTH_SHARED)
602                 auth_type[at_num++] = "shared";
603         if (cred->auth_type & WPS_AUTH_WPA)
604                 auth_type[at_num++] = "wpa-eap";
605         if (cred->auth_type & WPS_AUTH_WPA2)
606                 auth_type[at_num++] = "wpa2-eap";
607         if (cred->auth_type & WPS_AUTH_WPA2PSK)
608                 auth_type[at_num++] =
609                 "wpa2-psk";
610
611         if (cred->encr_type & WPS_ENCR_NONE)
612                 encr_type[et_num++] = "none";
613         if (cred->encr_type & WPS_ENCR_WEP)
614                 encr_type[et_num++] = "wep";
615         if (cred->encr_type & WPS_ENCR_TKIP)
616                 encr_type[et_num++] = "tkip";
617         if (cred->encr_type & WPS_ENCR_AES)
618                 encr_type[et_num++] = "aes";
619
620         if (wpa_s->current_ssid) {
621                 if (!wpa_dbus_dict_append_byte_array(
622                             &dict_iter, "BSSID",
623                             (const char *) wpa_s->current_ssid->bssid,
624                             ETH_ALEN))
625                         goto nomem;
626         }
627
628         if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
629                                              (const char *) cred->ssid,
630                                              cred->ssid_len) ||
631             !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
632                                                (const char **) auth_type,
633                                                at_num) ||
634             !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
635                                                (const char **) encr_type,
636                                                et_num) ||
637             !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
638                                              (const char *) cred->key,
639                                              cred->key_len) ||
640             !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
641                                          cred->key_idx) ||
642             !wpa_dbus_dict_close_write(&iter, &dict_iter))
643                 goto nomem;
644
645         dbus_connection_send(iface->con, msg, NULL);
646
647 nomem:
648         dbus_message_unref(msg);
649 }
650
651 #endif /* CONFIG_WPS */
652
653
654 /**
655  * wpas_dbus_signal_prop_changed - Signals change of property
656  * @wpa_s: %wpa_supplicant network interface data
657  * @property: indicates which property has changed
658  *
659  * Sends ProertyChanged signals with path, interface and arguments
660  * depending on which property has changed.
661  */
662 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
663                                    enum wpas_dbus_prop property)
664 {
665         WPADBusPropertyAccessor getter;
666         char *prop;
667
668         switch (property) {
669         case WPAS_DBUS_PROP_AP_SCAN:
670                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
671                 prop = "ApScan";
672                 break;
673         case WPAS_DBUS_PROP_SCANNING:
674                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
675                 prop = "Scanning";
676                 break;
677         case WPAS_DBUS_PROP_STATE:
678                 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
679                 prop = "State";
680                 break;
681         case WPAS_DBUS_PROP_CURRENT_BSS:
682                 getter = (WPADBusPropertyAccessor)
683                         wpas_dbus_getter_current_bss;
684                 prop = "CurrentBSS";
685                 break;
686         case WPAS_DBUS_PROP_CURRENT_NETWORK:
687                 getter = (WPADBusPropertyAccessor)
688                         wpas_dbus_getter_current_network;
689                 prop = "CurrentNetwork";
690                 break;
691         default:
692                 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
693                            __func__, property);
694                 return;
695         }
696
697         wpa_dbus_mark_property_changed(wpa_s->global->dbus,
698                                        wpa_s->dbus_new_path,
699                                        WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
700 }
701
702
703 /**
704  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
705  * @global: wpa_global structure
706  *
707  * Sends ProertyChanged signals informing that debug level has changed.
708  */
709 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
710 {
711         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
712                                        WPAS_DBUS_NEW_INTERFACE,
713                                        "DebugLevel");
714 }
715
716
717 /**
718  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
719  * @global: wpa_global structure
720  *
721  * Sends ProertyChanged signals informing that debug timestamp has changed.
722  */
723 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
724 {
725         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
726                                        WPAS_DBUS_NEW_INTERFACE,
727                                        "DebugTimestamp");
728 }
729
730
731 /**
732  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
733  * @global: wpa_global structure
734  *
735  * Sends ProertyChanged signals informing that debug show_keys has changed.
736  */
737 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
738 {
739         wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
740                                        WPAS_DBUS_NEW_INTERFACE,
741                                        "DebugShowKeys");
742 }
743
744
745 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
746                                void *priv,
747                                WPADBusArgumentFreeFunction priv_free,
748                                const struct wpa_dbus_method_desc *methods,
749                                const struct wpa_dbus_property_desc *properties,
750                                const struct wpa_dbus_signal_desc *signals)
751 {
752         int n;
753
754         obj_desc->user_data = priv;
755         obj_desc->user_data_free_func = priv_free;
756         obj_desc->methods = methods;
757         obj_desc->properties = properties;
758         obj_desc->signals = signals;
759
760         for (n = 0; properties && properties->dbus_property; properties++)
761                 n++;
762
763         obj_desc->prop_changed_flags = os_zalloc(n);
764         if (!obj_desc->prop_changed_flags)
765                 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
766                            __func__);
767 }
768
769
770 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
771         { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
772           (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
773           {
774                   { "args", "a{sv}", ARG_IN },
775                   { "path", "o", ARG_OUT },
776                   END_ARGS
777           }
778         },
779         { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
780           (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
781           {
782                   { "path", "o", ARG_IN },
783                   END_ARGS
784           }
785         },
786         { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
787           (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
788           {
789                   { "ifname", "s", ARG_IN },
790                   { "path", "o", ARG_OUT },
791                   END_ARGS
792           }
793         },
794         { NULL, NULL, NULL, { END_ARGS } }
795 };
796
797 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
798         { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
799           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
800           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
801           RW
802         },
803         { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
804           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
805           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
806           RW
807         },
808         { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
809           (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
810           (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
811           RW
812         },
813         { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
814           (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
815           NULL,
816           R
817         },
818         { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
819           (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
820           NULL,
821           R
822         },
823         { NULL, NULL, NULL, NULL, NULL, 0 }
824 };
825
826 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
827         { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
828           {
829                   { "path", "o", ARG_OUT },
830                   { "properties", "a{sv}", ARG_OUT },
831                   END_ARGS
832           }
833         },
834         { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
835           {
836                   { "path", "o", ARG_OUT },
837                   END_ARGS
838           }
839         },
840         { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
841           {
842                   { "properties", "a{sv}", ARG_OUT },
843                   END_ARGS
844           }
845         },
846         { NULL, NULL, { END_ARGS } }
847 };
848
849
850 /**
851  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
852  * @global: Pointer to global data from wpa_supplicant_init()
853  * Returns: 0 on success or -1 on failure
854  *
855  * Initialize the dbus control interface for wpa_supplicantand and start
856  * receiving commands from external programs over the bus.
857  */
858 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
859 {
860         struct wpa_dbus_object_desc *obj_desc;
861         int ret;
862
863         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
864         if (!obj_desc) {
865                 wpa_printf(MSG_ERROR, "Not enough memory "
866                            "to create object description");
867                 return -1;
868         }
869
870         wpas_dbus_register(obj_desc, priv->global, NULL,
871                            wpas_dbus_global_methods,
872                            wpas_dbus_global_properties,
873                            wpas_dbus_global_signals);
874
875         wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
876                    WPAS_DBUS_NEW_PATH);
877         ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
878                                        WPAS_DBUS_NEW_SERVICE,
879                                        obj_desc);
880         if (ret < 0)
881                 free_dbus_object_desc(obj_desc);
882         else
883                 priv->dbus_new_initialized = 1;
884
885         return ret;
886 }
887
888
889 /**
890  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
891  * wpa_supplicant
892  * @iface: Pointer to dbus private data from wpas_dbus_init()
893  *
894  * Deinitialize the dbus control interface that was initialized with
895  * wpas_dbus_ctrl_iface_init().
896  */
897 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
898 {
899         if (!iface->dbus_new_initialized)
900                 return;
901         wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
902                    WPAS_DBUS_NEW_PATH);
903         dbus_connection_unregister_object_path(iface->con,
904                                                WPAS_DBUS_NEW_PATH);
905 }
906
907
908 static void wpa_dbus_free(void *ptr)
909 {
910         os_free(ptr);
911 }
912
913
914 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
915         { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
916           (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
917           (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
918           RW
919         },
920         { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
921           (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
922           (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
923           RW
924         },
925         { NULL, NULL, NULL, NULL, NULL, 0 }
926 };
927
928
929 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
930         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
931           {
932                   { "properties", "a{sv}", ARG_OUT },
933                   END_ARGS
934           }
935         },
936         { NULL, NULL, { END_ARGS } }
937 };
938
939
940 /**
941  * wpas_dbus_register_network - Register a configured network with dbus
942  * @wpa_s: wpa_supplicant interface structure
943  * @ssid: network configuration data
944  * Returns: 0 on success, -1 on failure
945  *
946  * Registers network representing object with dbus
947  */
948 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
949                                struct wpa_ssid *ssid)
950 {
951         struct wpas_dbus_priv *ctrl_iface;
952         struct wpa_dbus_object_desc *obj_desc;
953         struct network_handler_args *arg;
954         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
955
956         /* Do nothing if the control interface is not turned on */
957         if (wpa_s == NULL || wpa_s->global == NULL)
958                 return 0;
959         ctrl_iface = wpa_s->global->dbus;
960         if (ctrl_iface == NULL)
961                 return 0;
962
963         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
964                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
965                     wpa_s->dbus_new_path, ssid->id);
966
967         wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
968                    net_obj_path);
969         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
970         if (!obj_desc) {
971                 wpa_printf(MSG_ERROR, "Not enough memory "
972                            "to create object description");
973                 goto err;
974         }
975
976         /* allocate memory for handlers arguments */
977         arg = os_zalloc(sizeof(struct network_handler_args));
978         if (!arg) {
979                 wpa_printf(MSG_ERROR, "Not enough memory "
980                            "to create arguments for method");
981                 goto err;
982         }
983
984         arg->wpa_s = wpa_s;
985         arg->ssid = ssid;
986
987         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
988                            wpas_dbus_network_properties,
989                            wpas_dbus_network_signals);
990
991         if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
992                                                wpa_s->ifname, obj_desc))
993                 goto err;
994
995         wpas_dbus_signal_network_added(wpa_s, ssid->id);
996
997         return 0;
998
999 err:
1000         free_dbus_object_desc(obj_desc);
1001         return -1;
1002 }
1003
1004
1005 /**
1006  * wpas_dbus_unregister_network - Unregister a configured network from dbus
1007  * @wpa_s: wpa_supplicant interface structure
1008  * @nid: network id
1009  * Returns: 0 on success, -1 on failure
1010  *
1011  * Unregisters network representing object from dbus
1012  */
1013 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1014 {
1015         struct wpas_dbus_priv *ctrl_iface;
1016         char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1017         int ret;
1018
1019         /* Do nothing if the control interface is not turned on */
1020         if (wpa_s == NULL || wpa_s->global == NULL)
1021                 return 0;
1022         ctrl_iface = wpa_s->global->dbus;
1023         if (ctrl_iface == NULL)
1024                 return 0;
1025
1026         os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1027                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1028                     wpa_s->dbus_new_path, nid);
1029
1030         wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1031                    net_obj_path);
1032         ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1033
1034         if (!ret)
1035                 wpas_dbus_signal_network_removed(wpa_s, nid);
1036
1037         return ret;
1038 }
1039
1040
1041 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
1042         { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1043           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1044           NULL,
1045           R
1046         },
1047         { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1048           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1049           NULL,
1050           R
1051         },
1052         { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1053           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1054           NULL,
1055           R
1056         },
1057         { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1058           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1059           NULL,
1060           R
1061         },
1062         { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1063           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1064           NULL,
1065           R
1066         },
1067         { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1068           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1069           NULL,
1070           R
1071         },
1072         { "Rates", WPAS_DBUS_NEW_IFACE_BSSID, "au",
1073           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
1074           NULL,
1075           R
1076         },
1077         { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1078           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1079           NULL,
1080           R
1081         },
1082         { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1083           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1084           NULL,
1085           R
1086         },
1087         { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1088           (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1089           NULL,
1090           R
1091         },
1092         { NULL, NULL, NULL, NULL, NULL, 0 }
1093 };
1094
1095
1096 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
1097         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1098           {
1099                   { "properties", "a{sv}", ARG_OUT },
1100                   END_ARGS
1101           }
1102         },
1103         { NULL, NULL, { END_ARGS } }
1104 };
1105
1106
1107 /**
1108  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1109  * @wpa_s: wpa_supplicant interface structure
1110  * @bssid: scanned network bssid
1111  * @id: unique BSS identifier
1112  * Returns: 0 on success, -1 on failure
1113  *
1114  * Unregisters BSS representing object from dbus
1115  */
1116 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1117                              u8 bssid[ETH_ALEN], unsigned int id)
1118 {
1119         struct wpas_dbus_priv *ctrl_iface;
1120         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1121
1122         /* Do nothing if the control interface is not turned on */
1123         if (wpa_s == NULL || wpa_s->global == NULL)
1124                 return 0;
1125         ctrl_iface = wpa_s->global->dbus;
1126         if (ctrl_iface == NULL)
1127                 return 0;
1128
1129         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1130                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1131                     wpa_s->dbus_new_path, id);
1132
1133         wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1134                    bss_obj_path);
1135         if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1136                 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
1137                            bss_obj_path);
1138                 return -1;
1139         }
1140
1141         wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1142
1143         return 0;
1144 }
1145
1146
1147 /**
1148  * wpas_dbus_register_bss - Register a scanned BSS with dbus
1149  * @wpa_s: wpa_supplicant interface structure
1150  * @bssid: scanned network bssid
1151  * @id: unique BSS identifier
1152  * Returns: 0 on success, -1 on failure
1153  *
1154  * Registers BSS representing object with dbus
1155  */
1156 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1157                            u8 bssid[ETH_ALEN], unsigned int id)
1158 {
1159         struct wpas_dbus_priv *ctrl_iface;
1160         struct wpa_dbus_object_desc *obj_desc;
1161         char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1162         struct bss_handler_args *arg;
1163
1164         /* Do nothing if the control interface is not turned on */
1165         if (wpa_s == NULL || wpa_s->global == NULL)
1166                 return 0;
1167         ctrl_iface = wpa_s->global->dbus;
1168         if (ctrl_iface == NULL)
1169                 return 0;
1170
1171         os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1172                     "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1173                     wpa_s->dbus_new_path, id);
1174
1175         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1176         if (!obj_desc) {
1177                 wpa_printf(MSG_ERROR, "Not enough memory "
1178                            "to create object description");
1179                 goto err;
1180         }
1181
1182         arg = os_zalloc(sizeof(struct bss_handler_args));
1183         if (!arg) {
1184                 wpa_printf(MSG_ERROR, "Not enough memory "
1185                            "to create arguments for handler");
1186                 goto err;
1187         }
1188         arg->wpa_s = wpa_s;
1189         arg->id = id;
1190
1191         wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1192                            wpas_dbus_bss_properties,
1193                            wpas_dbus_bss_signals);
1194
1195         wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1196                    bss_obj_path);
1197         if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1198                                                wpa_s->ifname, obj_desc)) {
1199                 wpa_printf(MSG_ERROR,
1200                            "Cannot register BSSID dbus object %s.",
1201                            bss_obj_path);
1202                 goto err;
1203         }
1204
1205         wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1206
1207         return 0;
1208
1209 err:
1210         free_dbus_object_desc(obj_desc);
1211         return -1;
1212 }
1213
1214
1215 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
1216         { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1217           (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1218           {
1219                   { "args", "a{sv}", ARG_IN },
1220                   END_ARGS
1221           }
1222         },
1223         { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1224           (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1225           {
1226                   END_ARGS
1227           }
1228         },
1229         { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1230           (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1231           {
1232                   { "args", "a{sv}", ARG_IN },
1233                   { "path", "o", ARG_OUT },
1234                   END_ARGS
1235           }
1236         },
1237         { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1238           (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1239           {
1240                   { "path", "o", ARG_IN },
1241                   END_ARGS
1242           }
1243         },
1244         { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1245           (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1246           {
1247                   { "path", "o", ARG_IN },
1248                   END_ARGS
1249           }
1250         },
1251         { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1252           (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1253           {
1254                   { "name", "s", ARG_IN },
1255                   { "data", "ay", ARG_IN },
1256                   END_ARGS
1257           }
1258         },
1259         { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1260           (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1261           {
1262                   { "name", "s", ARG_IN },
1263                   { "data", "ay", ARG_OUT },
1264                   END_ARGS
1265           }
1266         },
1267         { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1268           (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1269           {
1270                   { "name", "s", ARG_IN },
1271                   END_ARGS
1272           }
1273         },
1274 #ifdef CONFIG_WPS
1275         { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1276           (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1277           {
1278                   { "args", "a{sv}", ARG_IN },
1279                   { "output", "a{sv}", ARG_OUT },
1280                   END_ARGS
1281           }
1282         },
1283 #endif /* CONFIG_WPS */
1284         { NULL, NULL, NULL, { END_ARGS } }
1285 };
1286
1287 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
1288         { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1289           (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1290           NULL, R
1291         },
1292         { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1293           (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1294           NULL, R
1295         },
1296         { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1297           (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1298           NULL, R
1299         },
1300         { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1301           (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1302           (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1303           RW
1304         },
1305         { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1306           (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1307           NULL, R
1308         },
1309         { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1310           (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1311           NULL, R
1312         },
1313         { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1314           (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1315           NULL, R
1316         },
1317         { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1318           (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1319           NULL, R
1320         },
1321         { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1322           (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1323           NULL, R
1324         },
1325         { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1326           (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1327           NULL, R
1328         },
1329         { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1330           (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1331           NULL, R
1332         },
1333         { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1334           (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1335           NULL, R
1336         },
1337 #ifdef CONFIG_WPS
1338         { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1339           (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1340           (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1341           RW
1342         },
1343 #endif /* CONFIG_WPS */
1344         { NULL, NULL, NULL, NULL, NULL, 0 }
1345 };
1346
1347 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
1348         { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1349           {
1350                   { "success", "b", ARG_OUT },
1351                   END_ARGS
1352           }
1353         },
1354         { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1355           {
1356                   { "path", "o", ARG_OUT },
1357                   { "properties", "a{sv}", ARG_OUT },
1358                   END_ARGS
1359           }
1360         },
1361         { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1362           {
1363                   { "path", "o", ARG_OUT },
1364                   END_ARGS
1365           }
1366         },
1367         { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1368           {
1369                   { "name", "s", ARG_OUT },
1370                   END_ARGS
1371           }
1372         },
1373         { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1374           {
1375                   { "name", "s", ARG_OUT },
1376                   END_ARGS
1377           }
1378         },
1379         { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1380           {
1381                   { "path", "o", ARG_OUT },
1382                   { "properties", "a{sv}", ARG_OUT },
1383                   END_ARGS
1384           }
1385         },
1386         { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1387           {
1388                   { "path", "o", ARG_OUT },
1389                   END_ARGS
1390           }
1391         },
1392         { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1393           {
1394                   { "path", "o", ARG_OUT },
1395                   END_ARGS
1396           }
1397         },
1398         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1399           {
1400                   { "properties", "a{sv}", ARG_OUT },
1401                   END_ARGS
1402           }
1403         },
1404 #ifdef CONFIG_WPS
1405         { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1406           {
1407                   { "name", "s", ARG_OUT },
1408                   { "args", "a{sv}", ARG_OUT },
1409                   END_ARGS
1410           }
1411         },
1412         { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1413           {
1414                   { "credentials", "a{sv}", ARG_OUT },
1415                   END_ARGS
1416           }
1417         },
1418         { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1419           {
1420                   { "properties", "a{sv}", ARG_OUT },
1421                   END_ARGS
1422           }
1423         },
1424 #endif /* CONFIG_WPS */
1425         { NULL, NULL, { END_ARGS } }
1426 };
1427
1428
1429 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1430 {
1431
1432         struct wpa_dbus_object_desc *obj_desc = NULL;
1433         struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1434         int next;
1435
1436         /* Do nothing if the control interface is not turned on */
1437         if (ctrl_iface == NULL)
1438                 return 0;
1439
1440         /* Create and set the interface's object path */
1441         wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1442         if (wpa_s->dbus_new_path == NULL)
1443                 return -1;
1444         next = ctrl_iface->next_objid++;
1445         os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
1446                     WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1447                     next);
1448
1449         obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1450         if (!obj_desc) {
1451                 wpa_printf(MSG_ERROR, "Not enough memory "
1452                            "to create object description");
1453                 goto err;
1454         }
1455
1456         wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1457                            wpas_dbus_interface_properties,
1458                            wpas_dbus_interface_signals);
1459
1460         wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
1461                    wpa_s->dbus_new_path);
1462         if (wpa_dbus_register_object_per_iface(ctrl_iface,
1463                                                wpa_s->dbus_new_path,
1464                                                wpa_s->ifname, obj_desc))
1465                 goto err;
1466
1467         wpas_dbus_signal_interface_added(wpa_s);
1468
1469         return 0;
1470
1471 err:
1472         os_free(wpa_s->dbus_new_path);
1473         wpa_s->dbus_new_path = NULL;
1474         free_dbus_object_desc(obj_desc);
1475         return -1;
1476 }
1477
1478
1479 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1480 {
1481         struct wpas_dbus_priv *ctrl_iface;
1482
1483         /* Do nothing if the control interface is not turned on */
1484         if (wpa_s == NULL || wpa_s->global == NULL)
1485                 return 0;
1486         ctrl_iface = wpa_s->global->dbus;
1487         if (ctrl_iface == NULL)
1488                 return 0;
1489
1490         wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1491                    wpa_s->dbus_new_path);
1492         if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1493                                                  wpa_s->dbus_new_path))
1494                 return -1;
1495
1496         wpas_dbus_signal_interface_removed(wpa_s);
1497
1498         os_free(wpa_s->dbus_new_path);
1499         wpa_s->dbus_new_path = NULL;
1500
1501         return 0;
1502 }